Connect your catalog
A vs B keeps a Live Catalog: a single, always-fresh copy of every product. You connect it once, and from then on recommendations and commerce audiences all read the same product truth.
Connect your store (recommended)
The server-side sources give you a complete catalog: every product, not just those a shopper happened to browse. Full coverage, zero shopper-browser cost. Connect at least one.
In-browser collection only sees products that a shopper actively views. Products nobody has browsed recently simply never appear in recommendations or audiences. A server-side source (Shopify, a feed, the Push API, or an upload) sends your full catalog so every product is available from day one, regardless of traffic.
- Shopify: connect once and A vs B syncs automatically.
- Product feed: paste a feed URL to poll on a schedule.
- Push API: send products from your own server.
Shopify: connect once, sync automatically
Connecting your Shopify store imports the full catalog the moment you connect, then keeps it live automatically via webhooks. Products, variants, stock levels, and deletions stay current with no manual steps.
Go to Commerce → Sources → Shopify to connect. That page is where every store connection lives, Shopify, WooCommerce and BigCommerce alike, and where you re-sync or disconnect one later. See Connect Shopify for the full guide.
Feed import: schedule a product feed URL
Point A vs B at the URL where your store already publishes a Google Merchant Center XML feed and choose a refresh cadence (hourly, every 6 hours, or daily). A vs B fetches and parses the feed automatically.
On the Product catalog page, under Connect your store, use the Product feed card and select + Add product feed to configure. See Feed Import for the full guide.
Catalog Push API: send from your own server
Push product data programmatically from any server-side process: your own backend, a build pipeline, a scheduled job. Supports single upserts, batches up to 1,000 products, and a staged bulk flow for larger catalogs.
See Catalog Push API for routes, authentication, and the field reference.
Upload baseline: seed from a dataset
Upload a product table as a dataset, turn on Use this dataset as the Live Catalog source on that dataset's page, and A vs B imports a copy into the Live Catalog as a lowest-priority baseline every time you activate a version. Useful as a first step before a live source is ready, or as a safety floor that lives under all other sources.
See Upload Baseline for the setup steps, column mapping, and the priority rules.
Which source should I use?
| Shopify | Feed import | Push API | Upload baseline | |
|---|---|---|---|---|
| Coverage | Full: all products | Full: feed must include all products | Full: you control what is sent | Full: depends on your file |
| Freshness | Live (webhooks on every change) | Hourly to daily polling | Real-time (you push when you change) | On activation only |
| Exact price | Yes | Yes | Yes | Yes |
| Shopper-browser cost | None | None | None | None |
| Setup effort | Install the app, then a connect code | Paste a URL | Authenticate + script | Upload a file |
All sources feed the same merge queue. A higher-priority source always wins when it writes more recently. The order of priority is:
live browser event → Shopify webhook → Push API / feed → upload baselineCollect live data from your storefront (optional)
Once a server-side source is connected, you can optionally add the in-browser collection to capture real-time price changes and the exact price each shopper saw: useful for keeping recommendation cards price-accurate and for powering recently-viewed lists.
The in-browser collection reads product details your page already shows to the shopper: title, price, availability. It does not call your backend, it does not open any new endpoint, and it does not expose anything that was not already visible on the page. This is the standard "data layer" pattern used by analytics platforms worldwide. The data comes from your own markup; the snippet reads it.
The in-browser collection needs the A vs B snippet installed on your pages first. Copy your snippet tag from Project Settings → Snippet and paste it into your <head>: see Quick Install.
Option A: Explicit JavaScript
On each product page, call avsb.commerce.productView inside avsb.ready so the call is safely queued even if it runs before the snippet finishes loading:
// Wrap in avsb.ready: safe to call before the snippet loads.// The stub in your install tag queues the callback and drains it once ready.avsb.ready?.(function () { avsb.commerce.productView({ sku: 'SKU-123', // required: your stable product identifier title: 'Merino Wool Sweater', priceMinor: 8900, // price in minor units (cents): 8900 = $89.00 currency: 'USD', image: 'https://shop.example.com/img/sku-123.jpg', url: 'https://shop.example.com/products/merino-sweater', availability: 'in_stock', // 'in_stock' | 'out_of_stock' | 'preorder' });});Send priceMinor when you already have the price in the smallest unit of the currency (cents for USD/GBP/EUR, yen for JPY). If it is easier to send the displayed price (for example 89.00), use price instead and A vs B converts it using your project's currency setting. When both are present, priceMinor wins.
If the sku on your page identifies a variant (size, colour) rather than the product itself, also send productKey: the id of the parent product. All analytics (bestsellers, viewed-together, order lines) group by productKey, so two sizes of the same shirt count as one product. When you leave productKey out, it defaults to the sku you sent.
avsb.commerce.productView({ sku: 'SWEATER-M', // the variant on the page productKey: 'SWEATER', // the parent product id priceMinor: 8900,});Option B: Data attributes (no JavaScript required)
Add data-avsb-* attributes to your product markup. A vs B reads them on page load and whenever the placement changes. No snippet avsb.ready wrapper needed: the snippet picks them up after it loads.
<!-- Option A: one JSON blob on the product container --><div data-avsb-product='{ "sku": "SKU-123", "title": "Merino Wool Sweater", "priceMinor": 8900, "currency": "USD", "availability": "in_stock"}'></div><!-- Option B: discrete attributes --><div data-avsb-sku="SKU-123" data-avsb-title="Merino Wool Sweater" data-avsb-price="89.00"></div>Option C: Reuse your existing analytics
Already sending analytics events or structured data? Turn this on from the Product catalog page and A vs B reads your existing product details straight from them, no extra tagging on your pages.
- Google Analytics 4 / dataLayer: reads your existing GA4 ecommerce events (
view_item,add_to_cart,view_item_list) into the catalog. - JSON-LD product markup: reads
<script type="application/ld+json">Product nodes that are already on your pages.
A vs B never scrapes arbitrary markup. It only reads your data after you explicitly enable this for the project on the Product catalog page, so you stay in control of what is mapped.
A note on prices and currency
Inside the catalog, money is stored in minor units: the smallest unit of your currency (cents for USD/GBP/EUR, no subunit for JPY). 8900 means $89.00. A vs B uses your project's currency setting to know how many decimal places that means for each currency.
Prices are never shipped to the browser ahead of time. They resolve at the moment they are needed: so a price you change in your store shows up within the edge-cache window (about a minute) without a redeploy.
Verify we can see your products
Once a source is connected, open the Product catalog page for your project and watch the verification panel. For server-side sources, the panel updates as the import runs. For the in-browser collection, browse a product page on your store and it should appear within a few seconds:
- a status badge: Waiting for first product before anything arrives, then Receiving products once data is flowing
- a count of product views in the last 15 minutes
- the most recent product shown: its title, price, image, and availability
If a field looks wrong or is flagged as missing, fix your mapping and the panel updates on its next refresh (every 30 seconds while the tab is in view). This is your trust gate: when the product looks right here, every feature that reads the catalog has the same correct view.
- The status badge: Waiting for first product, then Receiving products.
- The most recent product, shown exactly as A vs B parsed it.
For server-side sources, check the source health card on the Product catalog page for an error message. For the in-browser collection, check that the A vs B snippet is installed on your product pages and that your mapping includes a real sku. If you are reading from your existing analytics, confirm that option is switched on for this project.
Check a product code
Not sure whether a specific SKU or variant code is understood by A vs B? On the Product catalog page, use Check a product code. Paste any code (a product SKU or an external variant code) and you will see exactly what it resolves to:
- A product: the code is a product in your catalog (you will see its title, price, and availability).
- A variant: the code is a variant that maps to a parent product (you will see which product it lands on).
- No match: nothing in your catalog matches the code as typed.
A vs B matches product codes exactly: it never trims or reformats them. If the code you pasted has an accidental leading or trailing space, the checker tells you that the trimmed version would match, and flags it as a warning rather than pretending it matched. Fix the stray spaces wherever the code is sent (your storefront, feed, or orders) so live matching stays reliable.
Each product's inspect drawer also lists Also known as (every external variant code that resolves to that product) so you can confirm the full set of codes that land on it.
Find products that need attention
The Is your catalog complete? card on the Product catalog page is a quick health check of the products you store. It shows how many products are:
- Missing a price: no price, or a price of zero.
- Missing an image: no image URL stored.
- No category: no primary category, which weakens category-based recommendations and audiences.
- Out of stock: currently unavailable.
- Click any figure to jump to just those products in the list below.
You can also use the filter chips above the product list at any time to narrow to one of these groups.
Export your catalog
Need the catalog as a spreadsheet? Use Export CSV in the product list toolbar. The export honours whatever search term and filter you have applied, so you can export just the products that need attention (for example, everything missing an image). Prices are formatted in each product's own currency. Very large catalogs are exported up to a fixed row limit; if that limit is reached, the file notes it in a final row so you know to narrow your filters.
Keep a product out of recommendations
Sometimes a product should never appear in recommendation feeds: a clearance item, a gift card, or something you would rather not cross-sell. Open the product in the inspect drawer and choose Exclude from recommendations. This adds a project-wide rule that removes the product from every recommendation feed, and it takes effect on the next publish. If a product is already excluded, the drawer says so. You can undo it later from your recommendation rules.
What the catalog stores per product
Every product in the Live Catalog has:
| Field | Where it comes from |
|---|---|
sku | Your unique product identifier: never changes |
title | Product name |
href | Canonical product page URL |
image | Main product image URL |
priceMinor | Price in minor units (integer) |
compareAtPriceMinor | Original/was price in minor units |
currency | ISO 4217 currency code |
availability | in_stock, out_of_stock, preorder, or removed |
category | Primary product type |
brand | Brand or manufacturer |
description | Product description (used by Similar products) |
variants | Variant list with per-variant price, stock, and availability |
customFields | Any extra attributes you send |
Fields you do not send are simply absent: they do not cause errors. The catalog stores whatever you give it and merges it with what other sources have sent.