Liquid template engine for the Braze variant by pure JavaScript: compatible to Braze, easy to extend.

Usage no npm install needed!

<script type="module">
  import shferreiraBrazejs from 'https://cdn.skypack.dev/@shferreira/brazejs';



npm npm Build Status Coveralls GitHub issues David David Dev DUB Commitizen friendly semantic-release

A braze compatible Liquid template engine in pure JavaScript. Built on top of liquidjs, with Braze tags/filters/syntax added and incompatible features removed.

Install via npm:

npm install --save brazejs

For detailed usage please refer to liquidjs' original doc.

Difference with liquidjs

Braze's liquid is a subset of Shopify's liquid, hence some incompatible features have to be removed. Braze also has it's own support for some Braze specific tags/filters/output, we add them in as plugin to liquidjs.


  • filters

    • abs: Braze doesn't support abs


  • Filters

  • Encoding

    | Filter Name | Example | Notes |
    | --- | --- | --- |
    | md5 | `{{"sample" \| md5}}` | |
    | sha1 | `{{"strings" \| sha1}}` | |
    | sha2 | `{{"to" \| sha2}}` | This is using SHA-256 |
    | hmac_sha1 | `{{"be" \| hmac_sha1}}` | |
    | base64 | `{{"encoded" \| base64}}` | |
    • URL

      Filter Name Example Notes
      url_escape {{"hey<>hi" \| url_escape}} ⚠️ this uses encodeURI which is slightly different from Braze's implementation
      url_param_escape {{"hey<>hi" \| url_param_escape}} ⚠️ this uses encodeURIComponent which is slightly different from Braze's implementation
    • Property Accessor

      Filter Name Example Notes
      property_accessor {{hash \| property_accessor: 'key'}} Example hash: { 'key' => 'hello' }
    • Number Formatting

      Filter Name Example Notes
      number_with_delimiter {{123456 \| number_with_delimiter}} ⚠️ this uses toLocaleString which is slightly different from Braze's implementation
    • JSON Escape

      Filter Name Example Notes
      json_escape {{'123"456' \| json_escape}} ⚠️ this uses JSON.stringify which is slightly different from Braze's implementation
  • Tags

    • abort_message: abort rendering and output an optional message


      {% abort_message() %}
      {% abort_message('aborted due to error') %}
    • connected_content: call an external API


      {% connected_content http://numbersapi.com/random/trivia :save trivia :cache 900 :basic_auth <secret_name> %}

      Supported options: :basic_auth, :content_type, :save, :cache, :method, :body

      For basic auth to work, you'll need to add the username and password into the context object.

      // replace <secret_name> so that it matches your basic auth name in Braze 
          "__secrets": {
              "<secret_name>": {
                  "username": "<your username>",
                  "password": "<your password>"
  • Output

    • ${} support for Personalization tags

      For it to work the attributes need to be added into context

          "first_name": "<my_name>",
          "user_id": "<my_uid>",
          "custom_attribute": {
              "<attr1>": "<val1>",
              "<attr2>": "<val2>"

      Then you can access them in the template:

      {{ ${first_name} }}
      {{ custom_attribute.${attr1} }}
    • Object will be converted to Ruby presentation

      If context is { "obj": {"foo": "bar"} }, liquidjs renders to [object Object], while brazejs renders it to {"foo"=>"bar"}

  • Content blocks

    • Content Blocks is supported


      By default the content blocks template is being searched in directories in following order:

        1. current dir
        2. content_blocks under current dir
        3. content_blocks in parent dir

      It will also search for file names in this order:

        1. exact match
        2. convert file name to kebab-case
        3. append .liquid
        4. convert file name to kebab-case and append .liquid

      It's also possible to configure the root dir and file extension in context:

            "__contentBlocks": {
                "root": "path_to_dir",
                "ext": ".html"

      ⚠️ At time of writing, Braze only support nesting 2 levels of content blocks

Use cases