Skip to main content
These examples use the full metafield namespace (app--326028230657--stockful) since they’re intended for custom theme code outside of Stockful’s own blocks. All examples assume storefront data is enabled in Stockful settings.

Stock status badge on product cards

Add a stock indicator to product cards on collection pages.
{% comment %}
  Add this inside your product card snippet (e.g. card-product.liquid).
  Uses the product-level stock_status metafield.
{% endcomment %}

{% assign status = product.metafields.app--326028230657--stockful.stock_status.value %}

{% if status == "low_stock" %}
  <span style="color: #ea580c; font-size: 0.85em;">Low Stock</span>
{% elsif status == "out_of_stock" %}
  <span style="color: #dc2626; font-size: 0.85em;">Out of Stock</span>
{% endif %}

”Selling Fast” badge

Highlight products that are top sellers based on velocity trend.
{% assign trend = product.metafields.app--326028230657--stockful.velocity_trend.value %}

{% if trend == "selling_fast" %}
  <div style="
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    padding: 0.3em 0.7em;
    background: #f3e8ff;
    color: #7c3aed;
    border-radius: 999px;
    font-size: 0.85em;
  ">
    <span style="width: 6px; height: 6px; border-radius: 50%; background: #7c3aed;"></span>
    Selling Fast
  </div>
{% endif %}

Urgency messaging on PDP

Show “Only X days left” when stock is running low.
{% assign variant = product.selected_or_first_available_variant %}
{% assign days = variant.metafields.app--326028230657--stockful.days_of_supply.value %}
{% assign status = variant.metafields.app--326028230657--stockful.stock_status.value %}

{% if status == "low_stock" and days and days <= 14 %}
  <p style="color: #ea580c; font-weight: 500;">
    {% if days <= 3 %}
      Almost gone - only {{ days }} {{ days | pluralize: 'day', 'days' }} of stock left
    {% else %}
      Only {{ days }} days of stock left
    {% endif %}
  </p>
{% endif %}

Social proof - units sold

Show how many units have sold recently to create confidence.
{% assign sold = product.metafields.app--326028230657--stockful.total_sold_30d.value %}

{% if sold and sold >= 20 %}
  <p style="font-size: 0.9em; opacity: 0.7;">
    {{ sold }}+ sold in the last 30 days
  </p>
{% endif %}

Restock messaging

Let customers know when out-of-stock items are being restocked.
{% assign variant = product.selected_or_first_available_variant %}
{% assign status = variant.metafields.app--326028230657--stockful.stock_status.value %}
{% assign restock = variant.metafields.app--326028230657--stockful.restock_status.value %}

{% if status == "out_of_stock" %}
  {% if restock == "pending" %}
    <p style="color: #2563eb;">Restock on the way - check back soon</p>
  {% elsif restock == "needed" %}
    <p style="color: #6b7280;">Currently out of stock</p>
  {% endif %}
{% endif %}

ABC-based merchandising

Highlight your A-class best sellers on collection pages.
{% assign abc = product.selected_or_first_available_variant.metafields.app--326028230657--stockful.abc_class.value %}

{% if abc == "A" %}
  <span style="
    display: inline-block;
    padding: 0.2em 0.6em;
    background: #fef3c7;
    color: #92400e;
    font-size: 0.8em;
    border-radius: 4px;
    font-weight: 500;
  ">
    Best Seller
  </span>
{% endif %}

Variant-aware badge with JavaScript

Update a custom badge when the customer changes variant on a PDP.
<div id="my-stock-badge"></div>

<script>
  function renderBadge(data) {
    var el = document.getElementById("my-stock-badge");
    if (!data || !data.stockStatus) {
      el.innerHTML = "";
      return;
    }

    var colors = {
      in_stock: "#16a34a",
      low_stock: "#ea580c",
      out_of_stock: "#dc2626"
    };
    var labels = {
      in_stock: "In Stock",
      low_stock: "Low Stock",
      out_of_stock: "Out of Stock"
    };

    if (data.velocityTrend === "selling_fast") {
      el.innerHTML = '<span style="color: #7c3aed;">Selling Fast</span>';
    } else {
      el.innerHTML = '<span style="color: ' + colors[data.stockStatus] + ';">'
        + labels[data.stockStatus] + '</span>';
    }
  }

  // Initial render
  if (window.stockful) {
    init();
  } else {
    window.addEventListener("stockful:ready", init);
  }

  function init() {
    var params = new URLSearchParams(window.location.search);
    var id = params.get("variant");
    if (id) {
      window.stockful.getVariant(Number(id)).then(renderBadge);
    }
  }

</script>

Location availability (custom implementation)

Build your own location availability UI instead of using the built-in drawer.
<button id="check-availability" type="button">Check store availability</button>
<div id="location-list" style="display: none;"></div>

<template id="location-row">
  <li style="display: flex; justify-content: space-between; padding: 0.5em 0; border-bottom: 1px solid #eee;">
    <div>
      <span data-name></span>
      <small data-city style="opacity: 0.6;"></small>
    </div>
    <span data-status></span>
  </li>
</template>

<script>
  const btn = document.getElementById("check-availability");
  const container = document.getElementById("location-list");
  const template = document.getElementById("location-row");

  btn.addEventListener("click", async () => {
    const variantId = new URLSearchParams(window.location.search).get("variant");
    if (!variantId || !window.stockful) return;

    container.style.display = "block";
    container.replaceChildren(Object.assign(document.createElement("p"), { textContent: "Loading..." }));

    const locations = await window.stockful.getLocationAvailability(Number(variantId));

    if (locations.length === 0) {
      container.replaceChildren(Object.assign(document.createElement("p"), { textContent: "No location data available." }));
      return;
    }

    const list = document.createElement("ul");
    list.style.cssText = "list-style: none; margin: 0; padding: 0;";

    for (const loc of locations) {
      const row = template.content.cloneNode(true);
      const inStock = loc.available > 0 || loc.status === "in_stock";

      row.querySelector("[data-name]").textContent = loc.name;

      const city = row.querySelector("[data-city]");
      if (loc.city) {
        city.textContent = ` (${loc.city})`;
      } else {
        city.remove();
      }

      const status = row.querySelector("[data-status]");
      status.style.color = inStock ? "#16a34a" : "#dc2626";
      status.textContent = loc.available != null
        ? (inStock ? `${loc.available} available` : "Out of stock")
        : (inStock ? "In stock" : "Out of stock");

      list.appendChild(row);
    }

    container.replaceChildren(list);
  });
</script>