Guide 01 · Developer docs

Choosing how to build

Decide where the pages of a Core dna site are composed before writing code: on the platform, in your own application, or on the platform with a few pieces filled in by the browser. The decision tree, each shape in depth, multi-brand and languages, and a table and case studies to make the call.

L2
Unit 05 · Multi-brand and multi-language

Content by region, without splitting the cache

Showing different content by region while the page cache keeps working. What a cached page is keyed on, region by hostname or path, region by a declared parameter, and the browser-then-fragment pattern a production site uses.

Who this is for. The developer asked to show regional prices, dates or offers on a cached site. After this page you can choose a way to condition content on region that keeps the page cache working, and you know the pattern a production site uses for it.

What a cached page is keyed on

The page cache stores a page under the hostname and path of the request, plus only the query parameters the template declares. A template declares a parameter by reading it with $_request->getParameter('name'), or explicitly with $_response->addCacheVaryParameter('name') or setCacheVaryParameters([...]).

Nothing else the request carries is part of the key. A template that branches on the visitor's location renders the branch for the first visitor, and that copy is then served to everyone on the same hostname and path. Region therefore has to be part of the key, as a hostname, a path or a declared parameter, or be resolved in the browser after the page is served.

Region by hostname or path

When each region has its own hostname, such as au.brand-one.example and nz.brand-one.example, or its own path, such as /au/ and /nz/, the cache already keeps one copy per region and the template needs nothing extra. A template can branch on $_currentSite->getHostname() freely, because the hostname is part of the key. Prefer this arrangement when regions differ in more than a block or two; Several hostnames on one site, or several sites covers how hostnames are arranged.

Region by a declared parameter

When the region arrives in the query string, declare the parameter, and the cache keeps one copy per value requested. That suits a handful of named values; a free-form value adds a copy for every value anyone requests. A touring site declares the two parameters its tour pages vary by, a presale code and a concert, in one line at the top of the template. The same call with a region:

Template code
{$_response->setCacheVaryParameters(['region'])}
{if $_request->getParameter('region') == 'nz'}
  {include file='includes/regional/nz-offers.html'}
{/if}
{{ _response.setCacheVaryParameters(['region']) }}
{% if _request.getParameter('region') == 'nz' %}
  {{ include('includes/regional/nz-offers.html') }}
{% endif %}

Region detected in the browser, then a fragment

When the region comes from the visitor's location rather than from the URL, keep the page the same for everyone and resolve the region in the browser. The touring site in the case studies resolves location in the browser, then requests a fragment:

  1. The page is cached once for every visitor. Its template calls enforceCaching() and holds an empty placeholder where the regional block goes.
  2. After the page loads, the site's script asks a geolocation service for the visitor's location once, keeps the answer in localStorage for a day, and fires an event when it is ready.
  3. A listener for that event requests a fragment with the location in its query string, and swaps the response into the placeholder.
  4. The fragment template reads the location with getParameter() and renders only the regional block.
Template code
{$_response->enforceCaching()}
...
<section id="regional-offers" aria-live="polite"></section>
{{ _response.enforceCaching() }}
...
<section id="regional-offers" aria-live="polite"></section>

The page stays one cached copy, and only the small fragment varies by region, after the page has painted. How a fragment template is served and requested is on Dynamic fragments; a script that is shipped only when such a feature is switched on is on A personalisation bundle that loads only when it is on.

Go deeper

Was this page helpful?

Your answer goes to the docs team.