Skip to content

Single CMS Page

About

The page(id:) query retrieves a single CMS (Content Management System) page. Use this query to:

  • Render a specific CMS page (e.g. About Us, Privacy Policy) in the storefront
  • Retrieve the full HTML content of a page for display
  • Access SEO metadata (meta title, description, keywords) for a specific page
  • Fetch locale-specific translation data for a page
  • Build dynamic page routes using urlKey
  • Validate whether a page exists before rendering

The query returns the page with translation — the single translation for the resolved locale — and translations, a cursor-paginated connection of every stored translation for that page. Use the pages query to list all available pages.

The id argument accepts both the IRI form (/api/shop/pages/1) and a plain numeric ID (1); both resolve to the same page.

Locale Handling

The locale is resolved per request, in this order:

  1. The X-Locale header, when the supplied code is one of the locales enabled on the current channel.
  2. The channel's default locale, when X-Locale is absent or names a locale the channel does not have enabled.

The two translation fields then behave as follows:

  • Resolved localetranslation carries the record for the locale resolved above.
  • Fallback — when the page has no translation for that locale, translation falls back to the application's fallback locale (en by default). If neither exists, translation is null.
  • Reported locale — the locale field inside translation always states which locale the returned content actually came from.
  • All languagestranslations is unaffected by the request locale. It returns every stored translation, so a client can cache all languages of a page in one call.

Arguments

ArgumentTypeRequiredDescription
idID!✅ YesIdentifier of the page — IRI form (/api/shop/pages/1) or numeric (1).

Possible Returns

Page Fields

FieldTypeDescription
idID!IRI-style unique identifier (e.g. /api/shop/pages/1).
_idInt!Numeric database ID.
layoutStringPage layout template name. null when no layout is assigned.
createdAtStringISO 8601 timestamp of when the page was created.
updatedAtStringISO 8601 timestamp of when the page was last updated.
translationPageTranslationTranslation for the resolved locale. null when the page has no translation at all.
translationsPageTranslationCursorConnectionCursor connection over every stored translation for this page.

PageTranslation Fields

Returned by translation and by each translations edge node.

FieldTypeDescription
idID!IRI-style ID of the translation record.
_idInt!Numeric translation record ID.
pageTitleString!Display title of the CMS page.
urlKeyString!URL slug used to access the page (e.g. about-us).
htmlContentStringFull HTML body content of the page.
metaTitleStringSEO meta title tag.
metaDescriptionStringSEO meta description tag.
metaKeywordsStringSEO meta keywords.
localeString!Locale code this translation belongs to (e.g. en, fr).
cmsPageIdString!ID of the page this translation belongs to.

Translations Connection Fields

FieldTypeDescription
edges[].nodePageTranslationA single translation record — fields as above.
edges[].cursorString!Cursor for this edge, used as after on the next request.
pageInfo.hasNextPageBoolean!Whether more translations follow the current slice.
pageInfo.hasPreviousPageBoolean!Whether translations precede the current slice.
pageInfo.startCursorStringCursor of the first edge in the slice.
pageInfo.endCursorStringCursor of the last edge in the slice.
totalCountIntTotal translations stored for this page.

Use Cases

1. Render a CMS Page

Fetch a specific page by ID and render its htmlContent on a dedicated page route in the storefront.

2. SEO Head Tags

Use metaTitle, metaDescription, and metaKeywords from the translation to populate <meta> tags dynamically.

3. Page Validation

Query a page before rendering to check whether it exists; handle a null page with a 404 page.

4. Multi-language Content

Send X-Locale to fetch a specific language, or read the whole translations connection to build a language switcher without one request per locale.

5. Dynamic Page Routing

Use urlKey to implement client-side routing so users access pages via human-readable URLs (e.g. /about-us).

Best Practices

  1. Send the storefront key — every storefront GraphQL request needs the X-STOREFRONT-KEY header; without it the request is rejected before the query runs
  2. Pick one ID form and keep it — both the IRI (/api/shop/pages/1) and the numeric (1) form work; the IRI form matches what id returns, so round-tripping a response value needs no conversion
  3. Check data.page and errors together — an unknown or malformed ID returns data.page as null with an entry in errors; treat that as a 404 rather than an outage
  4. Read translation.locale — it reports the locale the content actually came from, which differs from the requested one whenever the fallback applies
  5. Sanitize htmlContent — the field is raw HTML authored in the admin panel; sanitize it before injecting into the DOM
  6. Cache per page and locale — cache keyed by page ID alone will serve the wrong language once a second locale is enabled
  7. Fetch only needed fields — omit htmlContent and translations when only the title and URL are needed; both grow the response several times over, and htmlContent carries a full HTML body
  8. Use urlKey for links — build storefront URLs from urlKey for SEO-friendly, human-readable routes

Released under the MIT License.