Skip to content

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.

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.

// Always clear previous ecommerce data first
dataLayer.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 view_item_list
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.

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–11
dataLayer.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 viewport
dataLayer.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
}))
}
});

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 results
dataLayer.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 separately
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'view_item_list',
ecommerce: {
item_list_id: 'related_products',
item_list_name: 'Related Products',
items: [...]
}
});
  1. Create a Custom Event trigger. Triggers > New > Custom Event. Event name: view_item_list. Name it CE - view_item_list.

  2. Create Data Layer Variables. You need variables for ecommerce.items, ecommerce.item_list_id, and ecommerce.item_list_name. For the items array, the variable path is ecommerce.items.

  3. 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_id and item_list_name as additional event parameters if you want to filter on them in GA4
  4. Attach the trigger CE - view_item_list to the tag.

  5. Test in GTM Preview. Navigate to a category page. Confirm the event fires once with the correct items. Check that index values start at 0.

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.