view_item_list
The view_item_list event fires when a user sees a list of products. This is your product impression data — every time a product is visible to a user in a list context, you’re gathering data about which products get seen, which lists perform well, and how position affects downstream behavior.
This is the first event in the ecommerce funnel. The item_list_id and item_list_name you set here should carry through to select_item when the user clicks a product, creating a traceable path from list impression to product view to purchase.
When to fire
Section titled “When to fire”Fire view_item_list when:
- A category or subcategory page renders with products visible
- Search results load
- A recommendation widget or “related products” section is visible on the page
- A promotional product grid is visible (e.g., “New Arrivals”, “Sale Items”)
Do not fire it on every scroll — once per list render is correct. If pagination loads more products, fire again for the new page of results.
Complete dataLayer push
Section titled “Complete dataLayer push”// Always clear previous ecommerce data firstdataLayer.push({ ecommerce: null });
dataLayer.push({ event: 'view_item_list', ecommerce: { item_list_id: 'mens_outerwear', item_list_name: "Men's Outerwear", items: [ { item_id: 'SKU-001-BLK', item_name: 'Classic Leather Jacket', item_brand: 'Heritage Co.', item_category: 'Apparel', item_category2: 'Outerwear', item_category3: 'Jackets', item_variant: 'Black', price: 89.99, quantity: 1, index: 0, item_list_id: 'mens_outerwear', item_list_name: "Men's Outerwear" }, { item_id: 'SKU-023-NAV', item_name: 'Wool Peacoat', item_brand: 'Heritage Co.', item_category: 'Apparel', item_category2: 'Outerwear', item_category3: 'Coats', item_variant: 'Navy', price: 149.99, quantity: 1, index: 1, item_list_id: 'mens_outerwear', item_list_name: "Men's Outerwear" }, { item_id: 'SKU-041-GRN', item_name: 'Field Jacket', item_brand: 'Heritage Co.', item_category: 'Apparel', item_category2: 'Outerwear', item_category3: 'Jackets', item_variant: 'Olive Green', price: 119.99, quantity: 1, index: 2, item_list_id: 'mens_outerwear', item_list_name: "Men's Outerwear" } ] }});Event schema
Section titled “Event schema”| Parameter | Type | Required | Description |
|---|---|---|---|
| event | string | Required | Must be "view_item_list" |
| ecommerce.item_list_id | string | Optional | Machine-readable list identifier. Use snake_case. e.g., mens_outerwear, search_results. |
| ecommerce.item_list_name | string | Optional | Human-readable list name. e.g., "Men's Outerwear", "Search Results". |
| ecommerce.items[] | Array<Item> | Required | Array of product objects for all visible products in the list. |
| items[].item_id | string | Required | SKU or unique product identifier. |
| items[].item_name | string | Required | Product name. |
| items[].item_brand | string | Optional | Brand or manufacturer. |
| items[].item_category | string | Optional | Primary product category. |
| items[].item_variant | string | Optional | Default variant shown in the list. |
| items[].price | number | Optional | Current listed price. Number, not a string. |
| items[].quantity | number | Optional | Always 1 for list impression events. |
| items[].index | number | Optional | Position in the list, 0-based. Critical for position analysis. |
| items[].item_list_id | string | Optional | Same as ecommerce.item_list_id — repeat at item level to carry context forward. |
| items[].item_list_name | string | Optional | Same as ecommerce.item_list_name — repeat at item level. |
Handling large lists
Section titled “Handling large lists”Don’t include out-of-viewport products
Section titled “Don’t include out-of-viewport products”Only include products that are actually visible to the user when the event fires. If you have a 60-item category page with all products rendered in the DOM but only 12 visible above the fold, include only the visible products in the initial view_item_list push.
For lazy-loaded or infinite scroll lists, fire view_item_list again when new products enter the viewport. Increment the index values to reflect true position in the complete list.
// Initial viewport — products at index 0–11dataLayer.push({ ecommerce: null });dataLayer.push({ event: 'view_item_list', ecommerce: { item_list_id: 'search_results', item_list_name: 'Search Results', items: visibleProducts.map((product, i) => ({ ...product, index: i // 0 through 11 })) }});
// After scroll — next 12 products enter viewportdataLayer.push({ ecommerce: null });dataLayer.push({ event: 'view_item_list', ecommerce: { item_list_id: 'search_results', item_list_name: 'Search Results', items: nextBatchProducts.map((product, i) => ({ ...product, index: 12 + i // 12 through 23 })) }});Multiple lists on the same page
Section titled “Multiple lists on the same page”Pages often have multiple product lists: main search results, a “sponsored” widget, a “recently viewed” section. Fire a separate view_item_list for each distinct list, with unique item_list_id values.
// Main resultsdataLayer.push({ ecommerce: null });dataLayer.push({ event: 'view_item_list', ecommerce: { item_list_id: 'search_results', item_list_name: 'Search Results', items: [...] }});
// Related products widget fires separatelydataLayer.push({ ecommerce: null });dataLayer.push({ event: 'view_item_list', ecommerce: { item_list_id: 'related_products', item_list_name: 'Related Products', items: [...] }});GTM configuration
Section titled “GTM configuration”Step-by-step setup
Section titled “Step-by-step setup”-
Create a Custom Event trigger. Triggers > New > Custom Event. Event name:
view_item_list. Name itCE - view_item_list. -
Create Data Layer Variables. You need variables for
ecommerce.items,ecommerce.item_list_id, andecommerce.item_list_name. For the items array, the variable path isecommerce.items. -
Create the GA4 Event tag. Tags > New > Google Analytics: GA4 Event.
- Event Name:
view_item_list - Enable the Send Ecommerce data checkbox — this automatically maps the items array
- Optional: add
item_list_idanditem_list_nameas additional event parameters if you want to filter on them in GA4
- Event Name:
-
Attach the trigger
CE - view_item_listto the tag. -
Test in GTM Preview. Navigate to a category page. Confirm the event fires once with the correct items. Check that
indexvalues start at 0.
Common mistakes
Section titled “Common mistakes”Including all products regardless of visibility. If you push 60 products in view_item_list when only 12 are visible, your list performance data is inflated. Users “viewed” products that were never actually in their viewport.
Not including index. Position data is one of the most valuable outputs of list tracking. Which position in search results drives the most clicks? Without index, you cannot answer this. Always include it.
Forgetting the ecommerce null clear. Before every ecommerce push — including this one. Previous ecommerce events’ data will merge with this push if you skip the clear.
Inconsistent item_list_id across events. The list identifier you use on view_item_list must match what you use on select_item for that product. If they don’t match, GA4 cannot build cohesive list performance reports.