Skip to main content
This page shows the JavaScript API doing four jobs:
  • Send assignments to another tool, such as a tag manager or a data platform.
  • Render a custom price element, such as a bundle block ABConvert does not change.
  • Render a free shipping progress bar from the visitor’s shipping test.
  • Render an offer banner from the visitor’s offer test.
Each example is a script that runs in your theme. Treat it as a starting point: the selectors, IDs, and markup are for the store in the screenshot, so change them to match yours. The full scripts, with a playground you can run without a store, are in the ABConvert cookbook.
A mobile storefront product page with three script-rendered elements outlined and numbered: a free shipping bar above the header, a bundle block under the price, and an offer banner fixed to the bottom. The rest of the page, which the theme renders, is dimmed.

What the examples render: ① the free shipping bar, ② the bundle block, ③ the offer banner

The theme renders everything else on the page.
These scripts do not have to live in your theme. A visual editor test carries custom JavaScript per test group, so the script runs only for visitors in that test group and you end it from the ABConvert admin. Two rules differ from a theme script:
  • Add the code to a test group other than Control. Control cannot carry custom code.
  • Build any elements your script renders into inside the window.ABConvertQueue callback. Custom JavaScript runs before the page has a <body>.
Push the callback that builds the markup first; the queue runs callbacks in order.

Send assignments to another tool

Check the Integrations page in the ABConvert admin first. The Google Analytics 4 (GA4), Segment, and Heatmap integrations there send assignments with no theme code. Write this only for a tool that is not on that page, or for a tag manager that reads window.dataLayer. Every destination is the same loop: wait for ABConvert, then send one event per test. Send testGroup.index as the identifier, because you can rename a test group while the test runs.
Then write send for your destination:
The cookbook’s data platform example adds PostHog and Mixpanel destinations and sends each assignment once per session.

Render a custom price element

Product page detail: a card titled Add the wax kit lists Special ski wax at $62.70, written by the script, and Wax applicator at $6.00.

The bundle block, priced for this visitor's test group

ABConvert rewrites the price elements your theme renders on product and collection pages. A bundle block, promo block, or quick-view card you build yourself is not one of those, so it keeps showing the theme’s price. The bundle block in the screenshot is one of those. Mark the price of each product variant in it with class="custom-price" and the product variant’s ID. Leave the theme’s own price inside as the fallback for visitors who are not in the test:
Then add this script to your theme layout. Every marked element shows the price the visitor’s test group gets:
The visitor in the screenshot is in Variant A, so the script replaced the fallback $57.00 with their test price of $62.70. A visitor outside the test keeps the $57.00 the theme rendered, because getPriceByVariantId returns null for them. This runs once per page load. The cookbook’s custom price example adds the compare-at price and a data-product-id form for “From $X” cards. It also re-runs when the page changes, so product variant switches, Ajax collection filters, cart drawers, and lazy-loaded cards get the right price.

Render a free shipping progress bar

A pale green bar above a mobile storefront header reading Spend $51.00 more for free shipping, with a progress track about a third full.

The gap to the visitor's own free shipping threshold

The bar needs two numbers: the threshold from ABConvert, and the cart subtotal from Shopify. Read the subtotal with Shopify’s Ajax API. GET /cart.js returns items_subtotal_price in cents, in the cart’s currency. Add the bar to your theme with a child element for the text, so the script never overwrites the progress track:
Then add this function. A visitor in the test sees “Spend $51.00 more for free shipping” until the subtotal reaches the threshold, then “You have free shipping”:
Re-run renderShippingBar when the cart changes. Shopify’s Storefront Events API dispatches shopify:cart:lines-update, which bubbles to document, when the visitor changes cart lines. The event fires when the update starts, so before you read the cart, wait for event.promise:
A theme that changes the cart with Shopify.actions.updateCart always fires that event. A theme that posts to /cart/add.js directly fires it only when the theme’s own code dispatches it. If your theme does not, call renderShippingBar from the theme’s own cart event instead. Dawn publishes cart-update through the subscribe helper in assets/pubsub.js. That helper exists only after the theme’s scripts have run, so subscribe inside your queue callback, not at the top of your script. The cookbook’s free shipping bar example handles both, and covers a theme that fires neither.

Render an offer banner

A dark rounded card across the bottom of a mobile storefront reading Your offer, 30% off, with a white Shop now button.

The visitor's offer, pinned to the bottom

Add the banner to your theme with a child element for the title, so the script leaves the label and the button alone:
The script writes the title of the visitor’s first offer, “30% off” in the screenshot, and hides the banner when the visitor has no offer:
The cookbook’s offer banner example reads the cart’s item count and adds “You save 10%. Add 2 more items to save 20%” for a volume discount.