Advanced Statify Use cases

Extending Statify

Statify exposes a small browser API for adding custom client-side widgets and working with the generated page context. This is intended for integrations that do not belong in the built-in widgets, such as a shop, booking flow, interactive calculator, or service-specific component.

The API is available through window.statify:

const {install, resetCookies, m} = window.statify;
Member Purpose
install(widgets) Registers an object of named Mithril components so JSON pages can instantiate them as client-side widgets.
m Statify's Mithril instance. Use it instead of bundling a second copy of Mithril into the custom script.
resetCookies(currentPage=false) Clears Statify's locally stored consent and preferences, including the selected skin, and then reloads the website.
hasThirdParty() Whether the used has consented to use third party cookies
hasAnalytics() Whether the user has consented to use Analytics
stag(title, options) Record Analytics Events, if user has approved its usage

Calling resetCookies() reloads the site. Pass true to reload the current page instead:

window.statify.resetCookies(true);

This is useful for a button on the cookie-policy page that lets visitors reset their choices.

Installing a custom widget

Create a browser script containing one or more Mithril components. Load that custom script immediately after website.min.js and call statify.install(...) from within it, ideally at the end of the script, so the widgets are registered before Statify initializes the page.

For example, assets/res/custom-widgets.js could contain:

const {m, install, stag} = window.statify;

const PriceCalculator = {
    view({attrs}) {

        // JSON-declared attributes are available under attrs.static
        // query-string parameters may also be exposed by Mithril’s router, but the only 
        // supported parameter is subtype, provided by the /:subtype route. 

        const {title, quantity = 1, unitPrice = 0} = attrs.static;

        return m("section.price-calculator", [
            m("h2", title || "Price calculator"),
            m("p", `${quantity} × ${unitPrice} = ${quantity * unitPrice}`)
        ]);
    },
    oninit({attrs}) {
        // example: send to analytics that we are calculating price over an article
        stag("Price Calculator", {event: "price-calculator", props: {item: attrs.static.sku}})
    }
};

install({PriceCalculator});

Declare the application script first and the extension immediately after it in the head array of metadata.json:

{
  "head": [
    {"t": "script", "src": "app/website.min.js"},
    {"t": "script", "src": "res/custom-widgets.js"}
  ]
}

The registered name is then available to client-widget JSON. The declared attrs object is passed to the component as attrs.static:

{
  "widget": "Client",
  "client": {
    "widget": "PriceCalculator",
    "attrs": {
      "title": "Estimate your order",
      "quantity": 3,
      "unitPrice": 49
    }
  }
}

Widget names are case-sensitive. Register every widget before initialization, and avoid overwriting built-in or previously registered names. The simple application stub does not include Mithril or support external widget installation: install throws an exception there and m is unavailable.

The CODEX skill also knows how to generate these custom widgets.

Generated page context

Generated pages expose site and item information for integrations that need the current context:

Object Availability Contents
window.SITE Every page The site object from metadata.json.
window.ITEM Item detail pages The publication context: {item, list, listKey, relative, basePath, detailsMetadata}.

On a published list-item page, the normalized item itself is available as window.ITEM.item. Check that window.ITEM exists before accessing it from a script shared by ordinary and detail pages.