Resolving CMS pages
In many cases, a Storefront page directly corresponds to a CMS page. For instance, the Login page in the Storefront maps to a single CMS page entry. However, for pages like Product Listing or Product Details, where multiple instances exist, the mapping becomes more complex.
While some CMS platforms handle these mappings automatically, others do not. API Clients of our CMS integrations provide the tools to address these gaps, ensuring granular page-to-content mapping in more complex scenarios such as:
- mapping a group of Storefront pages to a common CMS page,
- mapping a group of Storefront pages to a common CMS page with specific exceptions, where some pages in that group are mapped to their own dedicated CMS pages,
- defining a fallback CMS page for all CMS-only and CMS-enhanced Storefront pages that do not have a corresponding CMS page.
The mechanism differs in each of our CMS integrations. Specific platform variations will be highlighted by the following guides.
In our Amplience integration, you can define two callbacks responsible for matching Storefront paths with CMS content entries:
resolvePages()
resolveFallbackPage()
They can be defined in the unified
configuration of the integration's API Client. Both can be asynchronous, which is useful if you want to maintain the mappings in the CMS, allowing content editors to manage them.
Page fetching flow
When the integration's getPage() method is called, it tries to fetch a page entry from Amplience in the following steps:
1
2
Fetching the resolved page
When the exact match strategy fails, getPage() will attempt to fetch a page based on the object returned by resolvePages(). The callback receives the integration's API Client context and request params as arguments. It has to return a map between Storefront page paths (or patterns) and objects containing the necessary data to fetch the appropriate CMS page entry.
export const config = {
configuration: {
unified: {
resolvePages: (context, params) => ({
"category/shoes": {
path: "category",
},
})
},
},
};
Based on the path received as one of the arguments, getPage() selects a single key from the map and uses its associated value (object) to request a page.
3
Fetching the fallback page
If the page resolution strategy fails, getPage() attempts to fetch a page based on the object returned by resolveFallbackPage(). The callback receives the same arguments as resolvePages() but has to return a single object containing the necessary data to fetch the fallback CMS page entry. Obviously, the fallback page entry has to exist in the CMS. If it does not, the getPage() request fails.
export const config = {
configuration: {
unified: {
resolveFallbackPage: (context, params) => ({
path: "fallback-page"
}),
}
}
}
One-to-One path mapping
Suppose you've a CMS entry for a Product Listing page and set its Path to category
. Now you want it to be fetched whenever users visit the category/shoes
path in the Storefront. For this you need to define a one-to-one relationship:
export const config = {
configuration: {
unified: {
resolvePages: (context, params) => ({
"category/shoes": {
path: "category",
},
})
},
},
};
It is a valid example, but also a redundant one. You could simply set your CMS page's Path to category/shoes
and the getPage()
method would resolve it automatically in the exact page match step. You could reuse the category
path also for other pages, like category/shirts
, category/pants
, but a more flexible approach would be to use Many-to-One path mapping.
Many-to-One path mapping
Suppose you've got the same CMS entry for a Product Listing page with Path set to category
. Now you want it to be fetched whenever users visit a certain group of paths in the Storefront. For this, you need to define a many-to-one relationship using a pattern (/category/*slug
) instead of a specific path:
export const config = {
configuration: {
unified: {
resolvePages: (context, params) => ({
"category/*slug": {
path: "category",
},
})
}
}
}
Internally, we use the path-to-regexp library to resolve Storefront paths and patterns. Refer to its documentation to explore available notation options.
If some Storefront paths fall into the category/*slug
pattern but you would like to fetch different CMS page entries for them, you can still leverage the exact page match strategy. For example, if you define a CMS page entry with Path equal to /category/shoes
, the Storefront will fetch it whenever users visit the /category/shoes
path. The category/*slug
mapping will be ignored.
Mappings order
When defining multiple mappings, ensure that the most specific paths appear first, followed by more general patterns. This prevents more general patterns from overshadowing specific ones.
Correct Example ✅
export const config = {
configuration: {
unified: {
resolvePages: (context, params) => ({
"category/shoes/nike": {
path: "category/shoes"
},
"category/*slug": {
path: "category",
},
})
}
}
}
Incorrect Example ❌
export const config = {
configuration: {
unified: {
resolvePages: (context, params) => ({
"category/*slug": {
path: "category",
},
/** This path will never be matched */
"category/shoes/nike": {
path: "category/shoes"
},
})
}
}
}
Read also
Now you know how to introduce complex relationships between your Storefront paths and CMS page entries. Read the other guides to learn even more about building amazing things with our CMS integrations.