Offer a free gift
Configure a shopper-claimed gift or a choice of gifts from a pool, choose its storefront integration, and verify that checkout enforces the free line.
Tab Promo models a free gift as a claimable reward, not an item silently inserted into the cart. The storefront explains that a gift is available, the shopper chooses to claim it, and the Shopify Discount Function makes the confirmed claim free at checkout.
Why the shopper must claim it
- The promise stays explicit. A shopper sees the available gift and decides whether to add it.
- Cart changes remain predictable. Themes do not have to recover from a background script silently changing quantities or opening a drawer.
- Checkout remains authoritative. Storefront JavaScript cannot make an item free. The Discount Function revalidates the marked line and applies the final discount.
If the cart later becomes ineligible, Tab Promo does not silently remove a claimed line. The storefront can offer a clear removal action, while checkout simply stops discounting an invalid claim.
Choose the claim surface
Before publishing, make sure the live theme has exactly one supported claim path:
- Official Theme Extension: turn on the Floating offers or Cart drawer offers app embed, or add the Product page offers block, wherever shoppers should see the gift. Tab Promo owns the claim CTA and normal theme lifecycle. Available on every plan while the store’s promotions are live.
- Custom theme: an implementation team using the published Storefront SDK renders the public gift facts and calls the SDK’s confirmed gift helpers after shopper consent. Install the release documented in the Storefront SDK guide. Requires Pro or Growth.
Do not run both claim renderers in the same placement. A published campaign without either path can qualify shoppers but gives them no supported way to claim the gift.
Configure the rule
Create or open a campaign, then add a rule whose action is Free gift.
Under Gift products, click Select products and choose the products shoppers can claim. Open a product’s menu and choose Edit selected variants to limit which of its variants are offered. A pool holds up to 20 products and 100 variants; one product with the right variants is a single gift with a choice of size or color.
Then set:
- Gift quantity — how many gifts a qualifying shopper can claim, from 1 to 20. Shoppers can claim them together or over several visits.
- Repeat policy — One gift per product, or Allow repeat gifts to let a shopper take several of the same product.
- An optional gift label in the message field.
The editor shows the Maximum retail gift value for the pool once variant prices are confirmed.
Rules saved before gift pools existed keep their single fixed variant or shopper-choice product, and they keep working at checkout and in the storefront. When you open one, the editor shows Update gift selection: the saved gift stays in place until you select replacement products.
The rule’s conditions control when the gift becomes eligible. A cart subtotal threshold is common, but customer, product, country, and other supported conditions can also gate a gift. At checkout, a claimed gift line does not count toward the cart subtotal or quantity used by those conditions.
The Free gift with purchase campaign template starts with a $50 cart subtotal threshold, a quantity of 1, One gift per product, and an empty pool. Select the gift products before publishing.
Official Theme Extension behavior
With the site-wide app embed active:
- An unqualified cart can show progress toward the reward when the campaign has a useful progress dimension.
- Once eligible, the extension shows a claim CTA. When a cart change unlocks the gift outside the cart page, a gift prompt also opens. Its decline button (No thanks by default, editable in the theme editor) hides the prompt for that gift for 24 hours; the claim CTA stays available.
- A gift pool opens the gift sheet, where the shopper picks up to the gift quantity. Each gift links to its product page in a new tab, so the shopper can look at it without claiming it. Every gift rule created in the admin is a pool, even with one product; only older rules with a single saved gift variant are claimed directly.
- After the click, Tab Promo adds and confirms the gift cart lines.
- Checkout independently verifies eligibility, ownership, selection, quantity, and the gift marker before applying the 100% discount. Units beyond the configured gift quantity are charged at the normal price.
A sold-out variant cannot be claimed. In a pool or a shopper-choice gift, unavailable variants stay disabled, and the gift is claimable only when at least one offered variant is available.
Custom theme with the SDK
Use the gift object returned with a promo, or the gift attached to the chosen
ladder rung. Do not derive a gift from the reward kind alone.
import { PromoSdkError } from '@tabcommerceio/promo-sdk'
async function claimGiftFromClick(gift, selectedVariantId) {
if (!gift.eligible) return
try {
const cart = await promo.claimGift({
gift,
...(selectedVariantId ? { variantId: selectedVariantId } : {}),
})
renderCart(cart)
} catch (error) {
if (error instanceof PromoSdkError) {
showGiftClaimError(error.code)
return
}
throw error
}
}
For a gift pool (selection: 'pool_choice'), let the shopper pick from the
gift’s candidates and pass every pick in one call as selections, an array of
{ variantId, quantity }. The Storefront SDK guide covers the quantity and
repeat rules and what to do when a claim is only partly confirmed. For a
shopper-choice gift, require the shopper to select one of the available
variants from the gift’s public display facts and pass that short numeric
variantId. For a pinned gift, call claimGift({ gift }) without manufacturing
an ID.
const cart = await promo.claimGift({
gift,
selections: [{ variantId: '44120001', quantity: 1 }],
})
Use the confirmed Shopify cart line key for a direct removal:
const cart = await promo.removeGift({ lineKey })
renderCart(cart)
Never write or copy the private gift cart property yourself. It is not a public integration contract.
The SDK also keeps storefront progress in line with checkout. It reports a claimed gift line to Tab Promo as a gift, so the gift doesn’t count toward the cart total or item count behind its own threshold, while conditions that only check whether a product is in the cart still see it. Its gift helpers match each claim to the exact rule that offered it.
Inspect and reconcile existing claims
Cart state can outlive the facts that originally created it: a campaign can end, a gift can become unavailable, or duplicate theme actions can leave more than one matching claim. Inspect first and let the shopper confirm any cleanup.
const facts = await promo.resolve({ surface: 'global' })
if (facts) {
const report = await promo.reconcileGiftClaims({ facts: facts.gift_facts })
showGiftClaimReview(report.claims)
if (shopperConfirmedCleanup) {
const updated = await promo.reconcileGiftClaims({
facts: facts.gift_facts,
remove: true,
})
if (updated.removedCart) renderCart(updated.removedCart)
}
}
inspectGiftClaims(cart, gifts) is also available as a pure report helper when
the theme already has both inputs. Neither inspection path removes anything by
default. gift_facts is an opaque snapshot attached to one accepted response;
do not serialize it or reuse a different surface’s snapshot.
Preview and verify
Use the Storefront sandbox to verify that the campaign produces the expected gift facts for an unqualified and qualified cart. Then publish on a development store and test the complete path:
- below and above the eligibility threshold;
- the gift sheet: picking up to the gift quantity, the repeat policy, and claiming the rest on a later visit;
- unavailable variants and duplicate clicks;
- claim, removal, and a cart that later becomes ineligible;
- a real checkout confirming that only a valid claimed line becomes free.
The sandbox cannot prove Cart AJAX or checkout behavior on its own.
What to avoid
- Publishing without a supported claim surface.
- Auto-adding or auto-removing a gift without shopper intent.
- Rendering a gift variant that is not offered and available in the current gift facts.
- Copying private cart properties or treating browser state as discount truth.
- Showing a successful claim before Shopify returns a confirming fresh cart.