Separate your HTML from your CSS with JSON Styles

In order to support a structured way to manage a/b testing and personalization, we highly recommend integrating Boxalino’s JSON Styles in your templates.

What this means is, in addition to the template content to be provided by Boxalino Narrative API, the selection of the style works simply with an additional parameter(s) of the template.

This will enable a structured way to manage many variations of the styles of your templates without “opening pandora’s box” and let the administrator type any style they want (and possibly break or at least make unsustainable your front-end over time).

What are JSON Styles?

Let’s start with dynamic content but no JSON Styles

Let’s imagine you integrated the title of the page with a Boxalino Narrative Layout Block, like here:

<h1 class="my-title-class"> {{ title }} </h1>

(in this case, “my-title-class” represents the class you decided to use for your title template).

If you leave it like this, then you have made the content of the template dynamic with Boxalino Narrative (as Boxalino Narrative can return a different value in the variable {{ title }} but you have not made the styling of your template dynamic.

What NOT TO DO next

You could of course make it configurable either by making the class dynamic and/or adding a dynamic style attribute like this:

<h1 class="my-title-class {{ title_class }}" style="{{ title_style }}"> {{ title }} </h1>

But this is not a practice we recommend for the following reasons:

  1. Adding (and possibly extending) classes as template parameters forces you to add more parameters to your narrative templates and rely on the hope that the administrator will know what class to define

  2. Letting the administrator type whatever he wants as a style is clearly the step too and the risk that your page will get bad rendering (or that the layout might break) is too high.

The solution with JSON Styles

What Boxalino recommends is, instead to create a separate JSON structure that connects your template to one of many styles of the template:

<h1 class="{{ style.title.class }}"> {{ title }} </h1>

with the following JSON styles:

This way, you will have one parameter in your Narrative template to return the style, but it will only indicate the name of the style (in this example: “default” or “red”).

As indicated here, we indicated that “red” extends “default”. This doesn’t do anything in this case (as there is only one class defined), but it is very helpful for cases where only a small subset of the classes are changed in a style (as in the full example below with “simple-red” extending “simple”).

The selected style would then be passed in a “style” template variable which would render the templates with the desired styles, but without ever letting the customer make changes that are uncontrolled and untested.

As per the full example below, we recommend you to structure your JSON Styles exactly with the same structure as your HTML, this will make them easy to read, map to your HTML, and maintain (for example, we defined “product.style.class” and to define the global style of the product template, “product.style.form.class” to define the class of the form component of the template and “product.style.form.title.class” to define the class of the title component of the form. Such direct mapping of the HTML and JSON Styles structure will make things much cleaner and easier to maintain.

Automatically generate the separation

While it is well suited for many cases to define your HTML templates and JSON Styles directly separately, there might be cases where it is not easily suitable, or creates an additional burden in the preparation of the templates.

For such a case, we recommend generating the two separated files (template with JSON Styles variables and JSON Styles) automatically with a script.

Expose your Template Schemas and JSON styles through git

Boxalino Intelligence Admin has a view called the “Layout Blocks” where they can be defined manually.

However, we also support automated integration through git with the following conditions:

  • A git repository managed by you provides (at least read-access over the cloud) to Boxalino Platform

  • A folder with all the templates is defined (can be anywhere in the repo)

  • Each template has a folder with its name (names will appear in the Narrative admin as Layout Blocks)

  • Each template folder has the following files and sub-folders:

    • template.* (extension might vary) : the HTML template file

    • schema.json: the JSON Schema of the Template

    • parameters.json: the JSON with the Layout Parameters (as would be defined in the Boxalino Admin)
      e.g.:
      [{
      "name": "magento_block_type",
      "values": ["Boxalino\Intelligence\Block\Journey\Product\ProductList"]
      },{
      "name": "magento_block_function_setTemplate",
      "values": ["Boxalino_Intelligence::journey/product/list.phtml"]
      },{
      "name": "bx-hits",
      "values": ["accessor"]
      },{
      "name": "position",
      "values": ["main"]
      }]

    • sub-folder “json-styles” with one file per JSON style with the content of the json inside (e.g.: file name “default.json” with content:
      { "title": { "class": "my-title-class" } }

Check-out a concrete example

You can find here a concrete single-page HTML example using Nunjucks as a template engine and Tailwind CSS to show you what it means in practice to apply JSON Styles.

In this example:

  • The HTML uses Tailwind & NunJucks (and jQuery, but only for the logic of the display)

  • the variable “product” represents a layout block returned by Boxalino Narrative API with the style “simple-red” selected

  • product_styles represent the map of all the defined product styles, with “simple-red” only extending one of the classes of “simple”, and “playful” showing a completely different style than “simple”

  • the Javascript Function extendStyle renders the styles (calling the applyExtension to apply the effects of extensions is one is defined)

  • The HTML defines the template itself (rendered with NunJucks by a jQuery call to renderProduct)