Liquid Variables

FirearmCart themes use Liquid templating. In addition to standard Liquid objects, FirearmCart provides custom variables tailored for firearms and ammunition retailers.


Overview

What is Liquid?

Liquid is a template language that allows you to:

  • Display dynamic content
  • Access product, collection, and store data
  • Create logic and loops
  • Use filters to transform data

Liquid Syntax

Objects - Output data:

{{ product.title }}
{{ shop.name }}

Tags - Logic and control:

{% if product.available %}
  In Stock
{% endif %}

Filters - Transform output:

{{ product.price | money }}
{{ product.title | upcase }}

FirearmCart Product Variables

product.specifications

Outputs an HTML table of product specifications. This is useful for displaying firearm details like caliber, barrel length, capacity, and other technical specifications.

Usage:

{{ product.specifications }}

Output Example:

For a product with specifications:

Name Value
Category Handguns
Model 1911 Commander
Caliber .45 ACP
Barrel Length 4.25"
State Restrictions CA

The variable outputs:

<table class="product-specifications">
  <tbody>
    <tr><th>Category</th><td>Handguns</td></tr>
    <tr><th>Model</th><td>1911 Commander</td></tr>
    <tr><th>Caliber</th><td>.45 ACP</td></tr>
    <tr><th>Barrel Length</th><td>4.25"</td></tr>
    <tr><th>State Restrictions</th><td>CA</td></tr>
  </tbody>
</table>

Styling:

Style the specifications table using the .product-specifications CSS class:

.product-specifications {
  width: 100%;
  border-collapse: collapse;
}

.product-specifications th,
.product-specifications td {
  padding: 8px 12px;
  border-bottom: 1px solid #e5e5e5;
  text-align: left;
}

.product-specifications th {
  font-weight: 600;
  width: 40%;
}

Notes:

  • Returns an empty string if no specifications are set
  • All values are HTML-escaped for security
  • Can be used in any template where the product object is available

product.sku

The product's SKU (Stock Keeping Unit) at the product level.

{{ product.sku }}

Example Output:

GLK-G19-GEN5-BLK

Note: For products with variants, each variant also has its own SKU accessible via product.selected_or_first_available_variant.sku.


product.barcode

The product's barcode (UPC, EAN, ISBN, etc.) at the product level.

{{ product.barcode }}

Example Output:

764503913150

Note: For products with variants, each variant also has its own barcode accessible via the variant object.


product.rating

Outputs inline SVG star rating based on product reviews. Displays filled and empty stars (e.g., 4 filled stars + 1 empty star for a 4.0 rating).

{{ product.rating }}

Output Example:

For a product with a 4.2 rating:

<span class="product-rating">
  <!-- Inline SVG stars: โ˜…โ˜…โ˜…โ˜…โ˜† -->
</span>

Important Notes:

  • Returns an empty string if no reviews exist
  • Uses the same star path geometry as the reviews widget
  • Output is inline SVG, not text characters
  • Can be used in custom liquid blocks

product.rating_full

Outputs stars plus a text summary showing the average rating and review count.

{{ product.rating_full }}

Output Example:

For a product with 37 reviews and a 4.2 average rating:

<span class="product-rating-full">
  <!-- SVG stars --> 4.2 (37 reviews)
</span>

Important Notes:

  • Returns an empty string if no reviews exist
  • Includes both visual stars and text summary
  • Can be used in custom liquid blocks

Using Product Ratings in Custom Liquid Blocks

Product rating variables are commonly used in custom liquid blocks within theme sections or custom code:

Basic Usage:

{# Just display stars #}
{{ product.rating }}

{# Display stars with text summary #}
{{ product.rating_full }}

Conditional Display:

Only show ratings if reviews exist:

{% if product.rating != '' %}
  <div class="product-reviews">
    {{ product.rating_full }}
  </div>
{% endif %}

In Product Cards:

<div class="product-card">
  <h3>{{ product.title }}</h3>
  <p>{{ product.price | money }}</p>

  {% if product.rating != '' %}
    {{ product.rating }}
  {% endif %}

  <a href="{{ product.url }}">View Product</a>
</div>

Styling:

You can style the rating output using CSS:

.product-rating {
  display: inline-block;
  vertical-align: middle;
}

.product-rating-full {
  font-size: 14px;
  color: #666;
}

Global Objects

shop

Store information available on every page:

{{ shop.name }}              # Store name
{{ shop.email }}             # Store email
{{ shop.description }}       # Store description
{{ shop.url }}               # Store URL
{{ shop.domain }}            # Store domain
{{ shop.currency }}          # Currency code (USD)
{{ shop.money_format }}      # Currency format

settings

Theme settings defined in settings_schema.json:

{{ settings.color_primary }}
{{ settings.type_body_font }}
{{ settings.logo }}

Theme-Level vs Section-Level:

{# Theme settings (global) #}
{{ settings.color_primary }}

{# Section settings (local to section) #}
{{ section.settings.heading }}

cart

Shopping cart information:

{{ cart.item_count }}        # Number of items
{{ cart.total_price | money }} # Cart total
{{ cart.items }}             # Array of cart items

{% for item in cart.items %}
  {{ item.product.title }} - {{ item.quantity }}
{% endfor %}

template

Current template being rendered:

{{ template }}               # Template name (e.g., "product", "collection")
{{ template.name }}          # Template name
{{ template.suffix }}        # Template suffix if any

routes

Route helpers for generating URLs:

{{ routes.root_url }}        # Home page
{{ routes.cart_url }}        # Cart page
{{ routes.all_products_collection_url }} # All products
{{ routes.search_url }}      # Search page
{{ routes.account_url }}     # Account page
{{ routes.account_login_url }} # Login page

request

Current request information:

{{ request.path }}           # Current URL path
{{ request.host }}           # Current host
{{ request.page_type }}      # Page type

Page-Specific Objects

product

Available on product pages:

{{ product.title }}          # Product name
{{ product.description }}    # Full description
{{ product.price | money }}  # Current price
{{ product.compare_at_price | money }} # Original price
{{ product.available }}      # In stock?
{{ product.type }}           # Product type
{{ product.vendor }}         # Manufacturer
{{ product.tags }}           # Product tags
{{ product.images }}         # Product images
{{ product.variants }}       # Product variants
{{ product.selected_or_first_available_variant }} # Current variant

{# FirearmCart specific #}
{{ product.specifications }} # Specifications table
{{ product.sku }}            # Product SKU
{{ product.barcode }}        # Product barcode
{{ product.rating }}         # Star rating (SVG)
{{ product.rating_full }}    # Stars + text summary

collection

Available on collection pages:

{{ collection.title }}       # Collection name
{{ collection.description }} # Collection description
{{ collection.products }}    # Products in collection
{{ collection.products_count }} # Number of products
{{ collection.image }}       # Collection image
{{ collection.url }}         # Collection URL

{% for product in collection.products %}
  {{ product.title }}
{% endfor %}

page

Available on CMS pages:

{{ page.title }}             # Page title
{{ page.content }}           # Page content (HTML)
{{ page.url }}               # Page URL
{{ page.handle }}            # Page handle/slug

article

Available on blog article pages:

{{ article.title }}          # Article title
{{ article.content }}        # Article content
{{ article.author }}         # Author name
{{ article.published_at | date: '%B %d, %Y' }} # Date
{{ article.image }}          # Featured image
{{ article.tags }}           # Article tags

blog

Available on blog pages:

{{ blog.title }}             # Blog title
{{ blog.articles }}          # Blog articles
{{ blog.articles_count }}    # Number of articles

{% for article in blog.articles %}
  {{ article.title }}
{% endfor %}

Available on search results pages:

{{ search.terms }}           # Search query
{{ search.results }}         # Search results
{{ search.results_count }}   # Number of results

{% for result in search.results %}
  {{ result.title }}
{% endfor %}

Section Objects

section

Available within sections:

{{ section.id }}             # Unique section ID
{{ section.settings.heading }} # Section setting value
{{ section.blocks }}         # Section blocks

{% for block in section.blocks %}
  {{ block.type }}           # Block type
  {{ block.settings.text }}  # Block setting
{% endfor %}

Important: Use section.settings.* for section-specific settings, NOT settings.* which is for global theme settings.


Common Filters

Money Formatting

{{ product.price | money }}
# Output: $599.99

{{ product.price | money_without_currency }}
# Output: 599.99

Date Formatting

{{ article.published_at | date: '%B %d, %Y' }}
# Output: January 15, 2025

{{ article.published_at | date: '%m/%d/%Y' }}
# Output: 01/15/2025

String Filters

{{ product.title | upcase }}
# Output: GLOCK 19 GEN 5

{{ product.title | downcase }}
# Output: glock 19 gen 5

{{ product.description | truncate: 100 }}
# Truncates to 100 characters

{{ product.description | strip_html }}
# Removes HTML tags

{{ product.handle | replace: '-', ' ' }}
# Replaces hyphens with spaces

Image Filters

{{ product.featured_image | image_url: width: 400 }}
# Image URL at 400px width

{{ product.featured_image | image_url: width: 400, height: 400 }}
# Image URL at specific dimensions

{{ product | image_url: width: 400 }}
# Product image shorthand

URL Filters

{{ 'cart' | url }}
# Cart URL

{{ product.url | within: collection }}
# Product URL within collection context

{{ 'base.css' | asset_url }}
# Theme asset URL

Translation Filter

{{ 'products.add_to_cart' | t }}
# Translated string from locale files

{{ 'products.items_count' | t: count: cart.item_count }}
# Translated with variable

Control Flow Tags

Conditionals

{% if product.available %}
  <button>Add to Cart</button>
{% else %}
  <button disabled>Out of Stock</button>
{% endif %}

{% if product.type == 'Firearm' %}
  <p>FFL Transfer Required</p>
{% elsif product.type == 'Ammunition' %}
  <p>Ground Shipping Only</p>
{% endif %}

{% unless product.available %}
  <span>Sold Out</span>
{% endunless %}

Loops

{% for product in collection.products %}
  <div class="product-card">
    {{ product.title }}
  </div>
{% endfor %}

{% for product in collection.products limit: 4 %}
  {# Show only first 4 #}
{% endfor %}

{% for product in collection.products offset: 4 %}
  {# Skip first 4 #}
{% endfor %}

Loop Variables:

{% for product in collection.products %}
  {{ forloop.index }}      # 1, 2, 3...
  {{ forloop.index0 }}     # 0, 1, 2...
  {{ forloop.first }}      # true for first item
  {{ forloop.last }}       # true for last item
  {{ forloop.length }}     # total count
{% endfor %}

Case/When

{% case product.type %}
  {% when 'Firearm' %}
    <p>Requires FFL Transfer</p>
  {% when 'Ammunition' %}
    <p>Ships Ground Only</p>
  {% else %}
    <p>Standard Shipping</p>
{% endcase %}

Variable Tags

assign

{% assign featured_product = collection.products.first %}
{{ featured_product.title }}

capture

{% capture product_info %}
  {{ product.title }} - {{ product.price | money }}
{% endcapture %}

{{ product_info }}

Including Templates

render

Include a snippet:

{% render 'product-card', product: product %}

With parameters:

{% render 'icon', icon: 'cart', size: 24 %}

section

Include a section:

{% section 'header' %}
{% section 'footer' %}

Best Practices

Check for Empty Values

{% if product.description != blank %}
  {{ product.description }}
{% endif %}

Use Default Values

{{ section.settings.heading | default: 'Featured Products' }}

Optimize Loops

{# Limit loops for performance #}
{% for product in collection.products limit: 12 %}
  ...
{% endfor %}

HTML Escape

{# Automatically escaped #}
{{ product.title }}

{# Raw HTML (use carefully) #}
{{ product.description }}