Substitution is almost synonymous with expansion in this context because their meanings overlap. Neither is quite a complete sub category of the other, although in the GNU Manual section you reference there are substitutions that are considered as part of an overall expansion.
An expansion is extracting the value of an identifier. E.g., if
this=that, when we expand
this we get
that. An expansion that doesn't involve substitution is pre-determined in that the value used already exists and must simply be retrieved, although this includes combining retrieved/explicit values (such as with "arithmetic expansion").
A substitution creates a value as the result of an explicit input/output operation. E.g., if
this is the result of executing
foo bar and capturing its output.1 Although the value resulting from a substitution maybe completely predictable, it is different from the one retrieved in a normal expansion because it does not actually exist until the substitution takes place -- it is produced.
Substitutions come in two flavours, command and process, which are sort of symmetrical:
# Command substitution
# Process substitution
The "command" in first one is
ls, as is the "process" in the second one. We might say what is being substituted is really the end of a pipe. Process substitution overlaps with redirection. However, this is probably a bit too under-the-hood restrictive technically, which brings us to the footnote...
foo bar in this case could be an internal shell function, in which case it there's no interprocess IO. The existence of shell built-ins less obviously obscures this difference. In terms of content the input and output will be the same.