How to give a context free grammar for any given language ie: a^n (ba)^m a^n
The reference question "How to prove that a language is context-free?" has some examples to build a context-free grammar using a simple toolbox. As is mentioned there one needs a "nesting structure" to make this work.

You ask about the difference between language like $L_1 = \{ab^na^nc \mid \dots \}$ and $L_2 = \{a^n (ab)^m a^n \mid \dots \}$. In both cases the parts that are iterated the same $n$ number of times have to be generated in parallel. Productions like $Y\to b Y a$ are good for that. 

In case of $L_1$ the $a\dots c$ pair is around the repeat $b^nc^n$ and can be generated before $S\to a X c$, but also independently as $S\to AXC, A\to a, C\to c$  .
In case of $L_2$ the $(ab)^m$ is inside the repeat $a^n\dots a^n$ and has to be generated after, like your own solution $S\to aSa, S\to X, X\to abX\mid \varepsilon$.