Loyalty Page: Building Custom Templates with CDN Scripts

A developer guide for building fully custom loyalty page layouts using the JeriCommerce CDN engine

For merchants who need full control over the HTML layout or want to build a completely custom loyalty page, JeriCommerce provides standalone Liquid section templates that load the loyalty page engine directly from the CDN. This guide is aimed at developers building custom storefront experiences for their merchants.

When to Use CDN Mode

Choosing Between the Default Block and CDN Templates

  • The merchant wants a completely custom layout that goes beyond what the theme editor settings allow.
  • The development team prefers to own the HTML directly in the theme code.
  • You need to integrate the loyalty page into an existing page template alongside other sections.

If the merchant is happy with the default look and just wants to tweak colors and copy, use the default template guide instead.

Setup Steps

Step 1: Get the Template

JeriCommerce provides two ready-made CDN templates. Copy the one that best fits your needs:

  • Visual template (templates/visual.liquid) — Full-featured: hero with CTA, how-it-works steps, earning rows with per-network SVG icons, tier cards, and loading skeleton. Same look as the theme block.
  • Minimal template (templates/minimal.liquid) — Compact list layout: title, earnings as a simple list, tiers as rows. Inline CSS, no external stylesheet needed.

You can obtain these from the JeriCommerce admin under Loyalty Page → Get template code, or copy directly from the repository files.

Step 2: Add to Your Theme

  1. Go to Shopify Admin → Online Store → Themes → Edit code.
  2. In the sections/ directory, click Add a new section.
  3. Name it (e.g., jeri-loyalty) and paste the template code.

Step 3: Create a Page Template

Create a JSON page template that references your section:

// templates/page.loyalty.json
{
  "sections": {
    "loyalty": {
      "type": "jeri-loyalty"
    }
  },
  "order": ["loyalty"]
}

Alternatively, add the section to an existing page template via the theme editor: Customize → Add section.

Step 4: Create the Page

Go to Shopify Admin → Pages → Add page → Select the "loyalty" template.

How CDN Mode Works

Loading the Engine

CDN templates load the same JavaScript that powers the theme app extension block — bundled, minified, and always up to date:

<!-- Always the latest version -->
<script src="https://cdn.jericommerce.com/shopify/loyalty-page.js" defer></script>
<link rel="stylesheet" href="https://cdn.jericommerce.com/shopify/loyalty-page.css" />

The engine auto-detects the shop domain from the data-shop attribute on the root element, or falls back to window.Shopify.shop.

Template System: How Data Binding Works

Two Complementary Mechanisms

The template engine uses two systems to bind API data to your HTML:

1. Variable Interpolation — {varName}

Write {varName} tokens anywhere in your HTML text content. The JS engine walks all text nodes and replaces them with API data. This is the primary way to display data.

<h3>{tier.name}</h3>
<span>{tier.requiredPoints}</span>
<span>{earning.points}</span>

Inside repeating templates (tiers, earnings), variables are scoped to the template data. Syntax uses single curly braces {key} — no conflict with Liquid ({{ }}), JS template literals (${ }), or CSS.

There are also global variables (like {programName}, {currencySymbol}) that work in any text node across the entire template — not just inside repeating templates. See the Global Template Variables section below for the full list.

2. Data Attributes — data-jeri

Used for non-text operations that can’t be expressed as text interpolation:

AttributePurposeExample
data-jeri="name" on <template>Defines a repeating row template<template data-jeri="tiers">
data-jeri="name" on containerReceives cloned template rows<div data-jeri="tiers">
data-jeri="key" on <img>Sets src attribute (hides if empty)<img data-jeri="earning.iconUrl">
data-jeri-hide-if="value"Hide element when data matches valuedata-jeri-hide-if="1"
data-jeri-html="key"Inject raw HTML content<p data-jeri-html="tier.content">
data-jeri-group="name"Group container (hidden when empty)data-jeri-group="purchases"

Quick Reference: When to Use Which

NeedUse
Display text/numbers{varName} in text content
Mix variables with custom copyEarn {earning.points} with {earning.title}
Set image srcdata-jeri="key" on <img>
Hide based on valuedata-jeri-hide-if
Inject rich HTML contentdata-jeri-html="key"
Define a repeating row<template data-jeri="name"> + <div data-jeri="name">

Global Template Variables

Variables Available Anywhere in the Template

These 7 global variables can be used in any text node inside #jeri-loyalty-page-root. Write them with {variableName} syntax — the engine replaces them automatically with data from the program configuration.

VariableTypeDescriptionExample
{programName}stringName of the loyalty program"My Rewards"
{currencySymbol}stringCurrency symbol for the program’s currency, resolved via the browser’s Intl.NumberFormat"$", "€", "£"
{currencyCode}stringISO currency code for the program"USD", "EUR", "GBP"
{balanceName}stringPlural name for points"Points", "Stars"
{singularBalanceName}stringSingular name for points"Point", "Star"
{tierBalanceName}stringPlural name for tier points"Points"
{singularTierBalanceName}stringSingular name for tier points"Point"

Usage Example

<h1>Welcome to {programName}!</h1>
<p>Earn {balanceName} with every {currencySymbol} you spend</p>
<p>Prices are in {currencyCode}</p>

Global variables work alongside scoped variables ({earning.*}, {tier.*}). Inside repeating templates, both global and scoped variables are resolved.

Note: The {currencySymbol} variable uses the browser’s native Intl.NumberFormat to resolve the correct symbol for the program’s currency code. This means the symbol adapts to the actual program currency — $ for USD, for EUR, £ for GBP, and so on.

Migration Note

The variable {hero.programName} has been removed. Use {programName} instead — it works everywhere in the template, not just in the hero section.

Available Data Fields

Earning Fields (earning.*)

Used inside the <template data-jeri="earning-row"> template.

FieldTypeDescription
earning.typestringFlow type: purchase, social, referral, profile, verify, wallet, scan, link
earning.titlestringHuman-readable title for the earning rule
earning.descriptionstringDetailed description of how to earn
earning.pointsstringCompact points display: "+100" for fixed points, "10%" for purchase return rate < 1, "x2" for purchase multiplier ≥ 1
earning.iconUrlstringIcon URL (set via data-jeri on <img>, empty if no icon). Social networks use per-network icons (facebook.svg, instagram.svg, etc.)

Tier Fields (tier.*)

Used inside the <template data-jeri="tiers"> template.

FieldTypeDescription
tier.namestringTier name (e.g., "Gold", "VIP")
tier.contentstringTier description/benefits — may contain HTML, use data-jeri-html="tier.content"
tier.imagestringTier image URL (set via data-jeri on <img>)
tier.requiredPointsstringPoints needed (e.g., "1,000 tier points"). Uses tierBalanceName with singular/plural
tier.factorstringPoints multiplier (e.g., "2"). Auto-hidden when "1" via data-jeri-hide-if
tier.idstringInternal tier ID

Required Root Element

The Foundation of Every Custom Template

Every custom template must include this root element with the required attributes:

<div
  id="jeri-loyalty-page-root"
  class="jeri-loyalty-page jeri-loyalty-page--loading"
  data-shop="{{ shop.permanent_domain }}"
  data-icon-base="https://cdn.jericommerce.com/shopify/"
  data-locale="{{ request.locale.iso_code }}"
>
  <!-- Your custom HTML here -->
</div>
AttributeRequiredPurpose
id="jeri-loyalty-page-root"YesJS entry point — the engine looks for this ID
class="jeri-loyalty-page"YesCSS scoping + CSS variables
data-shopYesShop domain for API calls
data-icon-baseRecommendedURL prefix for earning icons
data-localeRecommendedStore locale for i18n (falls back to "en")

The jeri-loyalty-page--loading class shows a skeleton and hides content until data loads. JS removes it after data is fetched.

Important: The CSS stylesheet must be loaded before the HTML content (inside the root element) to prevent a flash of unstyled content on first load.

Template Rules

The 6 Rules for Custom Templates

  1. Keep id="jeri-loyalty-page-root" on the root element — JS needs it to initialize.
  2. Keep class="jeri-loyalty-page" on root — CSS variables are defined here.
  3. Keep data-shop — required for API calls.
  4. Keep template/container pairs — A <template data-jeri="X"> needs a matching <div data-jeri="X"> as its sibling.
  5. Use {varName} freely in any text node — the engine replaces all tokens it recognizes.
  6. Use data-jeri-html="key" for HTML content (not {var}, which would be escaped).

Customizing the Default Template

What You Can Customize

The default template is fully customizable from the Liquid file. You can:

  • Change copy — Edit any text, mix {variables} with your own wording
  • Reorder sections — Move tiers above earnings, etc.
  • Remove sections — Delete any <section> you don’t want
  • Change HTML structure — Use tables, grids, lists, whatever fits your design
  • Add your own CSS — Use the Custom CSS setting or add <style> blocks

Example: Custom Earning Row Copy

<template data-jeri="earning-row">
  <div style="padding: 16px; border-bottom: 1px solid #eee;">
    <strong>{earning.title}</strong> — earn {earning.points}
    <p>{earning.description}</p>
  </div>
</template>
<div data-jeri="earnings-purchases"></div>
<div data-jeri="earnings-actions"></div>

Example: Custom Tier Card

<template data-jeri="tiers">
  <div class="my-tier">
    <h3>Tier: {tier.name}</h3>
    <p>Requires {tier.requiredPoints} to unlock</p>
    <span data-jeri="tier.factor" data-jeri-hide-if="1">
      Multiplier: {tier.factor}x
    </span>
    <div data-jeri-html="tier.content"></div>
  </div>
</template>

Rules for Custom Templates

  1. Keep id="jeri-loyalty-page-root" on the root element — JS needs it
  2. Keep class="jeri-loyalty-page" on root — CSS variables are defined here
  3. Keep data-shop — required for API calls
  4. Keep template/container pairs — <template data-jeri="X"> needs a matching <div data-jeri="X">
  5. Use {varName} freely in any text node — the engine replaces all tokens it recognizes
  6. Use data-jeri-html="key" for HTML content (not {var}, which would be escaped)

Default Template Structure

Hero Section

<section class="jeri-loyalty-page__hero">
  <h1 class="jeri-loyalty-page__hero-title">Our Loyalty Program</h1>
  <p class="jeri-loyalty-page__hero-subtitle">Join our loyalty program...</p>

  <!-- CTA adapts to login state via Liquid -->
  <div class="jeri-loyalty-page__hero-cta">
    {% if customer %}
      {% if block.settings.cta_action == 'widget_rewards' %}
        <a href="#jeri=loyalty/rewards" class="jeri-loyalty-page__cta-button jeri-loyalty-page__cta-button--primary">
          {{ block.settings.logged_in_cta_label | default: 'See rewards' }}
        </a>
      {% else %}
        <a href="{{ block.settings.logged_in_cta_url | default: '/account' }}" class="jeri-loyalty-page__cta-button jeri-loyalty-page__cta-button--primary">
          {{ block.settings.logged_in_cta_label | default: 'See rewards' }}
        </a>
      {% endif %}
    {% else %}
      <a href="{{ block.settings.guest_cta_url | default: '/account/login' }}" class="jeri-loyalty-page__cta-button jeri-loyalty-page__cta-button--primary">
        {{ 'loyalty_page.hero_cta' | t }}
      </a>
    {% endif %}
  </div>
</section>

Tiers Section

<template data-jeri="tiers">
  <div class="jeri-tier-card">
    <div class="jeri-tier-card__body">
      <div class="jeri-tier-card__top">
        <h3 class="jeri-tier-card__name">{tier.name}</h3>
        <span class="jeri-tier-card__factor" data-jeri="tier.factor" data-jeri-hide-if="1">
          {tier.factor}x
        </span>
      </div>
      <div class="jeri-tier-card__meta">
        <span class="jeri-tier-card__points">{tier.requiredPoints}</span>
      </div>
      <p class="jeri-tier-card__content" data-jeri-html="tier.content"></p>
    </div>
  </div>
</template>

<!-- Container: cloned cards are appended here -->
<div data-jeri="tiers" class="jeri-tier-grid"></div>

Earnings Section

<!-- Purchase earnings group -->
<div class="jeri-earning-group" data-jeri-group="purchases">
  <h3 class="jeri-earning-group__title">Purchases</h3>
  <div class="jeri-earning-list" data-jeri="earnings-purchases"></div>
</div>

<!-- Action earnings group -->
<div class="jeri-earning-group" data-jeri-group="actions">
  <h3 class="jeri-earning-group__title">Actions</h3>
  <div class="jeri-earning-list" data-jeri="earnings-actions"></div>
</div>

<!-- Shared template for both groups -->
<template data-jeri="earning-row">
  <div class="jeri-earning-row">
    <img class="jeri-earning-row__icon" data-jeri="earning.iconUrl" alt="" width="48" height="48" loading="lazy" />
    <div class="jeri-earning-row__content">
      <h3 class="jeri-earning-row__title">{earning.title}</h3>
      <p class="jeri-earning-row__description">{earning.description}</p>
    </div>
    <span class="jeri-earning-row__points">{earning.points}</span>
  </div>
</template>

Full Custom Template Example

Minimal Custom Implementation

Here is a complete minimal custom template to use as a starting point:

<!-- CDN Scripts -->
<script src="https://cdn.jericommerce.com/shopify/loyalty-page.js" defer></script>
<link rel="stylesheet" href="https://cdn.jericommerce.com/shopify/loyalty-page.css" />

<div
  id="jeri-loyalty-page-root"
  class="jeri-loyalty-page jeri-loyalty-page--loading"
  data-shop="{{ shop.permanent_domain }}"
  data-icon-base="https://cdn.jericommerce.com/shopify/"
  data-locale="{{ request.locale.iso_code }}"
>

  <!-- Hero -->
  <section class="jeri-loyalty-page__hero">
    <h1 class="jeri-loyalty-page__hero-title">Our Loyalty Program</h1>
    <p class="jeri-loyalty-page__hero-subtitle">Join and start earning rewards today.</p>
    <div class="jeri-loyalty-page__hero-cta">
      {% if customer %}
        <a href="/account" class="jeri-loyalty-page__cta-button jeri-loyalty-page__cta-button--primary">
          See rewards
        </a>
      {% else %}
        <a href="/account/login" class="jeri-loyalty-page__cta-button jeri-loyalty-page__cta-button--primary">
          Join now
        </a>
      {% endif %}
    </div>
  </section>

  <!-- Tiers -->
  <template data-jeri="tiers">
    <div>
      <h3>{tier.name}</h3>
      <p>{tier.requiredPoints}</p>
      <span data-jeri="tier.factor" data-jeri-hide-if="1">
        Multiplier: {tier.factor}x
      </span>
      <div data-jeri-html="tier.content"></div>
    </div>
  </template>
  <div data-jeri="tiers"></div>

  <!-- Earnings -->
  <template data-jeri="earning-row">
    <div>
      <img data-jeri="earning.iconUrl" alt="" width="32" height="32" />
      <strong>{earning.title}</strong>
      <span>{earning.points}</span>
      <p>{earning.description}</p>
    </div>
  </template>
  <div data-jeri-group="purchases">
    <h3>Purchases</h3>
    <div data-jeri="earnings-purchases"></div>
  </div>
  <div data-jeri-group="actions">
    <h3>Actions</h3>
    <div data-jeri="earnings-actions"></div>
  </div>

  <!-- Loading skeleton -->
  <div class="jeri-loyalty-page__skeleton">
    <div class="jeri-loyalty-page__skeleton-hero"></div>
  </div>

</div>

Visual vs Minimal Template

Choosing the Right Starting Point

Visual template — Best for brands that want a polished, marketing-style loyalty page with hero section, how-it-works steps, earning rows with SVG icons, tier cards, and full loading skeleton.

Minimal template — Best for stores that want a clean, data-first approach with compact list layout, inline CSS, and no external stylesheet dependency beyond the JS engine.

Both templates use the same JS engine and data binding system. The only difference is the HTML structure and visual design. You can start from either one and customize freely.

Icon System

How Earning Icons Work

Earning row icons are SVG files named by type. The icon URL is computed as data-icon-base + name + .svg.

Icon FileUsed For
purchase.svgPurchase earning flows
facebook.svgFollow on Facebook
instagram.svgFollow on Instagram
tiktok.svgFollow on TikTok
x.svgFollow on X
youtube.svgFollow on YouTube
referral.svgRefer a friend
profile.svgComplete profile
wallet.svgInstall wallet pass
scan.svgScan in store
verify.svgVerify account
link.svgVisit link

In CDN mode, the icon base URL is hardcoded to https://cdn.jericommerce.com/shopify/. If data-icon-base is missing or an icon doesn’t exist, the <img> element is hidden automatically.

Points Display Format

Compact Format Reference

The earning.points field uses a compact format depending on the earning type:

Earning typeFormatExample
Purchase (rate < 1)Percentage return10%
Purchase (rate >= 1)Multiplierx2
All others (social, referral, profile, etc.)Fixed points+100

For referral, only the referrer’s points are shown in the badge. The friend’s reward is mentioned in the description text.

The purchase earning description now uses the program’s actual currency symbol dynamically (e.g., "Earn x3 Points per $ spent" for USD, "Earn x3 Points per € spent" for EUR). The currency is resolved from the program configuration using the browser’s Intl.NumberFormat.

Wallet Names Resolution

Four Naming Properties

Four naming properties are resolved from the program config:

NameUsed forExample
balanceName / singularBalanceNameEarning descriptions, titles"points" / "point"
tierBalanceName / singularTierBalanceNameTier required points"tier points" / "tier point"

These are read from program.configurations.wallet (base config). Singular/plural is applied automatically based on the amount (1 = singular, else plural).

These four names are also available as global template variables — {balanceName}, {singularBalanceName}, {tierBalanceName}, and {singularTierBalanceName} — so you can reference them directly in any text node. See the Global Template Variables section above for the full list.

Theme Editor Settings

Configuration Reference

SettingTypeDefaultDescription
Enable Loyalty PagecheckboxtrueShow/hide the entire block
Hero Titletext"Our Loyalty Program"Main heading
Hero Subtitletextarea"Join our loyalty..."Description below heading
Guest CTA URLurl/account/loginWhere to send guests
Logged-in CTA Actionselectaccountaccount = go to account page, widget_rewards = open rewards widget
Logged-in CTA Labeltext"See rewards"Button text shown to logged-in customers
Logged-in CTA URLurl/accountURL when action is "Go to account page"
Show How It WorkscheckboxtrueToggle the 3-step section
Show Earning RulescheckboxtrueToggle the earnings section
Show VIP TierscheckboxtrueToggle the tiers section
Primary Colorcolor#0f0f0fButtons, accents, badges
Primary Contrastcolor#fcfcfcText on primary backgrounds
Secondary Colorcolor#f5f5f5Card backgrounds
Text Colorcolor#0f0f0fHeadings and body text
Muted Colorcolor#888888Subtitles, descriptions
Custom CSStextareaAdditional CSS overrides

Widget Integration

How the Page and Widget Complement Each Other

The "See rewards" CTA (when cta_action is set to widget_rewards) uses #jeri=loyalty/rewards as its href. When the JeriCommerce widget is active on the page, clicking this link opens the widget’s rewards panel. This means:

  • The loyalty page explains the program (public info)
  • The widget handles rewards, transactions, and account management (authenticated)
  • Both work independently but complement each other via the #jeri= URL pattern

Conditional Visibility

Auto-Hidden Elements

The page automatically hides elements based on program configuration:

ElementCondition
VIP Tiers sectionHidden when program has no tiers
Ways to Earn sectionHidden when program has no active engagement flows
Purchases groupHidden when no purchase-type flows exist
Actions groupHidden when no action-type flows exist

CSS Variables

Merchant-facing Variables

These are set on :root by the Liquid template based on theme editor color settings:

VariableDefaultSet by
--jeri-loyalty-primary#0f0f0fPrimary Color setting
--jeri-loyalty-primary-contrast#fcfcfcPrimary Contrast setting
--jeri-loyalty-secondary#f5f5f5Secondary Color setting
--jeri-loyalty-text#0f0f0fText Color setting
--jeri-loyalty-muted#888888Muted Color setting

Internal Variables

These resolve the merchant variables and add layout/structural tokens. Override them in Custom CSS for fine-grained control:

VariableDefaultPurpose
--jlp-primaryvar(--jeri-loyalty-primary, #0f0f0f)Primary color
--jlp-primary-contrastvar(--jeri-loyalty-primary-contrast, #fcfcfc)Text on primary
--jlp-textvar(--jeri-loyalty-text, #0f0f0f)Body text color
--jlp-mutedvar(--jeri-loyalty-muted, #888888)Secondary text color
--jlp-fontvar(--font-body-family, system stack)Font family
--jlp-border-radius16pxBorder radius for cards
--jlp-space16pxBase spacing unit
--jlp-border-color#e8e8e8Card/list border color
--jlp-card-bg#fcfcfcCard background color
--jlp-divider#f0f0f0Row divider color
--jlp-skeleton-bg#f5f5f5Skeleton loader color
--jlp-icon-size48pxEarning row icon size
--jlp-max-width1200pxPage max-width

Example: Override spacing via Custom CSS

.jeri-loyalty-page {
  --jlp-space: 12px;
  --jlp-border-radius: 8px;
}

Example: Dark theme via Custom CSS

.jeri-loyalty-page {
  --jlp-card-bg: #1a1a1a;
  --jlp-border-color: #333;
  --jlp-divider: #2a2a2a;
  --jlp-skeleton-bg: #222;
}

CSS Classes Reference

Layout

ClassElement
.jeri-loyalty-pageRoot container
.jeri-loyalty-page--loadingLoading state (shows skeleton, hides content)
.jeri-loyalty-page__heroHero section
.jeri-loyalty-page__sectionContent section
.jeri-loyalty-page__section-titleSection heading
.jeri-loyalty-page__skeletonSkeleton wrapper

Hero

ClassElement
.jeri-loyalty-page__hero-titleHero heading
.jeri-loyalty-page__hero-subtitleHero description
.jeri-loyalty-page__hero-ctaCTA button wrapper
.jeri-loyalty-page__cta-buttonCTA button base
.jeri-loyalty-page__cta-button--primaryPrimary CTA variant

How It Works

ClassElement
.jeri-loyalty-page__stepsSteps grid (3-column)
.jeri-loyalty-page__stepIndividual step
.jeri-loyalty-page__step-numberCircle with number
.jeri-loyalty-page__step-titleStep heading
.jeri-loyalty-page__step-textStep description

Earnings

ClassElement
.jeri-earning-groupGroup wrapper (Purchases/Actions)
.jeri-earning-group__titleGroup heading
.jeri-earning-listBordered list container
.jeri-earning-rowIndividual earning row
.jeri-earning-row__iconRow icon (<img>)
.jeri-earning-row__contentRow text wrapper
.jeri-earning-row__titleRow title
.jeri-earning-row__descriptionRow description
.jeri-earning-row__pointsPoints display

Tiers

ClassElement
.jeri-tier-gridTier cards flex container
.jeri-tier-cardIndividual tier card
.jeri-tier-card__bodyCard body
.jeri-tier-card__topName + factor row
.jeri-tier-card__nameTier name
.jeri-tier-card__factorMultiplier badge (hidden when 1x)
.jeri-tier-card__contentDescription (rendered as HTML)
.jeri-tier-card__pointsRequired points

Internationalization (i18n)

Language Support

The loyalty page supports multiple languages based on the store’s current locale.

Supported Languages

  • English (en) — default
  • Spanish (es)
  • French (fr)
  • German (de)
  • Italian (it)

Unsupported locales fall back to English automatically.

How It Works

There are two layers of i18n:

  1. Liquid-side strings (server-rendered): Uses Shopify’s {{ 'key' | t }} filter with locale JSON files in locales/. These translate static text like "Purchases", "Actions", "How It Works" steps, and the guest CTA button.
  2. TypeScript-side strings (client-rendered): Uses the shared i18n.ts utility with locale .ts files bundled into the JS. These translate dynamic earning flow titles and descriptions.

Locale Detection

The store locale is passed to JavaScript via the data-locale attribute on the root element:

<div id="jeri-loyalty-page-root" data-locale="{{ request.locale.iso_code }}" ...>
</div>

Adding a New Language

  1. Create theme-extensions/loyalty-page/locales/{lang}.ts (copy en.ts and translate)
  2. Create theme-extensions/loyalty-page/locales/{lang}.json (copy en.default.json and translate)
  3. Import the new locale in loyalty-page.ts and add it to initFromSession(locale, { en, es, fr, de, it, {lang} })
  4. Run npm run build:theme-extensions to rebuild

Translation Files

FilePurpose
locales/en.tsEnglish translations for JS-side strings (bundled into JS)
locales/es.tsSpanish translations for JS-side strings (bundled into JS)
locales/fr.tsFrench translations for JS-side strings (bundled into JS)
locales/de.tsGerman translations for JS-side strings (bundled into JS)
locales/it.tsItalian translations for JS-side strings (bundled into JS)
locales/en.default.jsonEnglish translations for Liquid-side strings (copied to output locales/)
locales/es.jsonSpanish translations for Liquid-side strings (copied to output locales/)
locales/fr.jsonFrench translations for Liquid-side strings (copied to output locales/)
locales/de.jsonGerman translations for Liquid-side strings (copied to output locales/)
locales/it.jsonItalian translations for Liquid-side strings (copied to output locales/)

Topics

Integrations