Branded spend bar in the cart drawer
Cart subtotal at least $100 → 10% off the order
With $72 in the cart, the API returns a progress fact: $72 of $100, $28 remaining, 72%. Your drawer shows "$28 from 10% off" in your own type.
Tab Promo has a Storefront promotion API and a JavaScript SDK (@tabcommerceio/promo-sdk) that your theme's own browser code calls directly, with no API key, no secret and no backend server for you to host. Requests go through your store's Shopify App Proxy, which signs each one, and Tab Promo works out the shop and the logged-in customer on its side. Your theme receives plain promotion facts, such as progress toward a threshold, a tier ladder or eligibility, and renders them in its own design, while Shopify checkout still decides every discount. Where checkout already shows them, facts can also carry the merchant's own campaign title and checkout label, so the theme doesn't have to invent offer copy.
See it work

theme/assets/promo.js
import { init } from
'@tabcommerceio/promo-sdk'
const promo = init({
proxyBase: '/apps/tab-promo',
})
promo.mount({
request: { surface: 'cart' },
render({ promos }) {
// progress, ladder, status
promos.forEach(drawBrandUi)
},
})SOLÈNE
Almost there. $28 from 10% off your bag.
Response
A tier offer comes back as a ladder: every rung with its threshold, reward and the tier name you set in Tab Promo, plus where the cart sits now. Amounts are in minor units. Because every tier is named, checkout shows the tier names, so the ladder carries no separate display message. Your theme renders it however it likes; checkout still applies the discount.
{
"campaign_id": "0192f0a3-d3a1-7000-8000-000000000001",
"primitive": "ladder",
"unit": "quantity",
"current": 7,
"current_rung": 0,
"next_rung": 1,
"remaining_to_next": 3,
"rungs": [
{
"name": "Buy 5",
"threshold": 5,
"reward": { "kind": "product_fixed", "amount": 500 },
"achieved": true
},
{
"name": "Buy 10",
"threshold": 10,
"reward": { "kind": "product_fixed", "amount": 1200 },
"achieved": false
}
]
} Examples
Cart subtotal at least $100 → 10% off the order
With $72 in the cart, the API returns a progress fact: $72 of $100, $28 remaining, 72%. Your drawer shows "$28 from 10% off" in your own type.
Product quantity tiers: 2+ → 10% off, 3+ → 15%, 4+ → 20% (counted per variant)
With 2 of the selected variant in the cart, the ladder fact marks the 10% tier as reached and 1 more item to reach 15%. Your theme draws the table.
Cart subtotal at least $50 → free tote bag
Your button calls claimGift. The SDK only resolves once Shopify returns a cart containing the gift, and checkout re-checks the claim before making it $0.
Customer tag is "VIP" and Cart subtotal at least $75 → Free shipping
Your code sends no customer ID. Shopify passes the logged-in customer with the signed request, so tagged VIPs get the offer and guests do not.
Setup
Good to know
Plan: Pro — $99/month (Free and Starter include the ready-made theme app embeds, not the API). Compare plans
FAQ
No. It returns promotion facts as JSON (progress, ladder and status, with rewards, gifts and top-up products), and the SDK renders nothing. Your theme owns the markup, copy, accessibility, localization and styling. Tier rungs carry the tier names you set in Tab Promo.
Yes, when Shopify checkout already shows them. A fact can carry a display object: title is the campaign name, present only when checkout uses it as the label of an automatic-discount rule that has no label of its own, and message is the rule's own checkout discount label. Each is left out when blank, when the message would repeat the title, or when checkout never shows it, such as a tier ladder whose tiers all have names. Both are plain text from the published campaign, exactly as written; your theme inserts them as text and handles translations.
No. Your theme calls it from the browser through your store's Shopify App Proxy. Shopify signs each request, Tab Promo rejects any request without a valid signature, and the shop and logged-in customer are read from that signed request. There is no key to store and no middleware to host.
Yes. That is what the SDK is for. Create a client with your relative /apps/... App Proxy path, then call resolve or mount from any script in your theme.
Yes, two ways. On every plan, the Tab Promo theme app embeds and product-page block show offers, with text and display settings in the theme editor. From Pro, your developer can build fully custom offer UI with the Storefront SDK.
No. Promotion facts need Pro or Growth; on Free and Starter the request is refused and the SDK returns nothing. Free and Starter stores use the ready-made theme app embeds, and the endpoint that lists top-up product choices works on every plan with live promotions.
Not today. The API is reached through Shopify's App Proxy on the store's own Online Store domain, and the SDK reads and updates the cart with Shopify's Online Store cart endpoints.
No. The API only describes offers. The discount is calculated inside Shopify checkout, which checks the cart again, including any free gift claim, before applying anything.
More with Tab Promo