Identifying Products on Your Site
The Data Collector reads product identifiers directly from your pages. Those identifiers are what connects a visitor's behavior to your catalogue, so recommendations, search and reporting all depend on getting them right.
The one hard rule
Every product ID that appears on your site must exist in the Item Feed as <id>.
If the site says 12345 and the feed says SKU-12345, nothing joins: the item is invisible to personalization even though both systems look correct in isolation. Same value, same casing, same padding — no transformation on either side.
Product cards
A product card is any tile representing a product: category listings, search results, carousels, cart lines, and blocks you render yourself from a recommendation API. Put the identifier on the root element of the card — the element that wraps the image, name and price:
<div class="product-card" data-per-item-id="12345">
<a href="/product/…"><img …></a>
<h3>…</h3>
<span class="price">…</span>
</div>The collector uses cards to emit impressions (a card became visible) and clicks (a visitor clicked a card), together with the position of the card in its list.
For cards, the identifier must be in the markup. Impressions and clicks are resolved from the element that entered the viewport or was clicked, so the collector has to be able to read the ID from that element. A value that lives only in adataLayer, a JavaScript variable or an API response cannot be attached to the right card — there is no reliable way to tell which of twenty tiles it belongs to.
Product detail
Put the identifier on the root element of the detail page — the container of the whole product section:
<div id="product-detail" data-per-item-id="12345">
…
</div>This is what produces the item view event: the signal that the visitor actually looked at this product. It is the single most important input for recommendations, so a detail page without an identifier costs more than a listing without one.
If your detail page is a single-page application and the product changes without a page reload, tell us — we bind to your navigation or dataLayer event so a new item view is emitted on each product.
Variants (optional)
If your catalogue has variants (size, colour, dimension), you can additionally expose the variant the visitor currently has selected:
<div id="product-detail" data-per-item-id="12345" data-per-variant-id="12345-RED-160x230">Keep data-per-variant-id updated when the visitor switches variant. If the change is announced through a dataLayer event, give us the event name instead — for the detail page we can bind to it.
Which identifier belongs on which surface is agreed with you during onboarding, because catalogues differ. The usual arrangement is:
| Surface | Identifier |
|---|---|
| Listing and search cards | master product |
| Product detail | master product, plus the selected variant if available |
| Add to cart, cart, order | the variant actually being sold |
Both master and variant IDs must be present in the item feed, linked through <grouping_id> — see Item Feed.
Already have an identifier in your markup?
data-per-item-id is the convention we recommend, but the collector is configured per site and can read an existing attribute instead — data-product-id, data-sku, a value inside a nested element, or whatever your platform already emits.
Do not restructure your templates for us. Tell us what is already there and where, and we configure the collector against it. That is faster and less risky for both sides than introducing new attributes.
Checklist
- Every ID on the site exists verbatim in the item feed.
- Product cards carry the ID on the card root, in the rendered markup.
- The product detail page carries the ID of the product being viewed.
- Variant-aware detail pages expose the selected variant and update it on change (optional).
- Add to cart, cart and order confirmation expose the IDs actually being purchased.
Related
- Item Feed — where every ID used on the site must also exist
- Marking Rendered Recommendations — cards you render from a recommendation API need these same identifiers, plus attributes on the wrapping block
- Marking Rendered Search Results — autocomplete and search results you render from the Search API, including categories, brands, articles and suggested queries
- Data Collector — the script that reads the identifiers from your pages
Updated about 13 hours ago

