Inventory & Stock Tracking
What This Means
Inventory tracking issues occur when you're not properly monitoring product availability, stock levels, and out-of-stock events in your analytics. Without this data, you can't identify lost revenue opportunities, optimize inventory levels, or understand how stock availability impacts customer behavior.
Key Inventory Metrics:
- Out-of-stock product views and attempted purchases
- Low stock threshold alerts
- Back-in-stock notifications and conversions
- Product availability by variant (size, color, etc.)
- Inventory impact on conversion rates
Impact Assessment
Business Impact
- Lost Revenue Unknown: Can't quantify sales lost to stockouts
- Inventory Mismanagement: Don't know which products to restock urgently
- Poor Customer Experience: Customers encounter unavailable products
- Missed Opportunities: Can't capture demand for out-of-stock items
- Inefficient Marketing: Advertising products that are unavailable
Analytics Impact
- Incomplete Funnel Data: Don't know how many users abandon due to stockouts
- False Performance Metrics: Products appear unpopular when actually out of stock
- Attribution Gaps: Can't separate availability issues from product quality issues
- Poor Forecasting: Missing demand signals for inventory planning
Common Causes
Implementation Gaps
- No tracking when users view out-of-stock products
- Stock status not included in product data layer
- Variant availability not tracked separately
- Back-in-stock events not monitored
Data Quality Issues
- Real-time inventory not synced with analytics
- Stock status cached and outdated
- Variant stock levels not granular enough
- Third-party inventory systems not integrated
Technical Problems
- AJAX cart updates don't reflect stock changes
- Checkout allows adding out-of-stock items
- Inventory webhooks not triggering events
- Stock status updates delayed
How to Diagnose
Check for Stock Status Tracking
// Monitor product views with stock status
window.dataLayer = window.dataLayer || [];
const originalPush = dataLayer.push;
dataLayer.push = function(...args) {
args.forEach(event => {
if (event.event === 'view_item') {
const items = event.ecommerce?.items || [];
items.forEach(item => {
console.log('📦 Product View:', {
name: item.item_name,
stock_status: item.stock_status || '⚠️ MISSING',
stock_quantity: item.stock_quantity || '⚠️ MISSING'
});
if (!item.stock_status) {
console.error('Missing stock_status for:', item.item_name);
}
});
}
});
return originalPush.apply(this, args);
};
Validate Stock Data in Data Layer
// Check if out-of-stock products are being tracked
function checkStockTracking() {
const stockStatus = document.querySelector('.stock-status')?.textContent.toLowerCase();
const isOutOfStock = stockStatus?.includes('out of stock') ||
stockStatus?.includes('unavailable');
const viewItemEvents = dataLayer.filter(e => e.event === 'view_item');
const latestEvent = viewItemEvents[viewItemEvents.length - 1];
console.log('Current Stock Status:', stockStatus);
console.log('Tracked Stock Status:', latestEvent?.ecommerce?.items?.[0]?.stock_status);
if (isOutOfStock) {
if (!latestEvent?.ecommerce?.items?.[0]?.stock_status) {
console.error('⚠️ Out-of-stock product viewed but not tracked!');
} else {
console.log('✓ Out-of-stock status tracked correctly');
}
}
}
checkStockTracking();
Check GA4 Custom Dimensions
Verify you have custom dimensions set up for:
- stock_status - In Stock, Out of Stock, Low Stock, Backorder
- stock_quantity - Numeric inventory level
- availability_date - When item will be back in stock
- variant_availability - Stock by size/color/variant
General Fixes
1. Track Stock Status in Product Views
// Include stock information in view_item events
function trackViewItem(product, stockInfo) {
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'view_item',
ecommerce: {
currency: 'USD',
value: product.price,
items: [{
item_id: product.id,
item_name: product.name,
item_brand: product.brand,
item_category: product.category,
item_variant: product.variant,
price: product.price,
quantity: 1,
// Stock information
stock_status: stockInfo.status, // 'in_stock', 'out_of_stock', 'low_stock', 'backorder'
stock_quantity: stockInfo.quantity,
low_stock_threshold: stockInfo.lowThreshold,
availability_date: stockInfo.availableDate
}]
},
// Also as top-level for easier reporting
stock_status: stockInfo.status,
stock_quantity: stockInfo.quantity
});
}
// On product page load
if (isProductPage()) {
const product = getProductData();
const stockInfo = getStockInfo();
trackViewItem(product, stockInfo);
}
2. Track Out-of-Stock Interaction Events
// Custom event when user tries to add out-of-stock item
function trackOutOfStockAttempt(product) {
dataLayer.push({
event: 'out_of_stock_attempt',
product_id: product.id,
product_name: product.name,
product_category: product.category,
requested_quantity: product.requestedQuantity,
stock_status: 'out_of_stock',
user_action: 'add_to_cart_attempt'
});
}
// Attach to disabled "Add to Cart" buttons
document.querySelectorAll('.add-to-cart[disabled]').forEach(button => {
button.addEventListener('click', (e) => {
e.preventDefault();
const productData = {
id: button.dataset.productId,
name: button.dataset.productName,
category: button.dataset.productCategory,
requestedQuantity: parseInt(document.querySelector('[name="quantity"]')?.value || 1)
};
trackOutOfStockAttempt(productData);
// Show notification
alert('This item is currently out of stock. Sign up for back-in-stock notifications!');
});
});
3. Track Inventory in Cart Events
// Include stock status in add_to_cart events
function trackAddToCart(product, quantity) {
const stockInfo = getStockInfo(product.id, product.variant);
// Verify stock availability
if (quantity > stockInfo.quantity) {
dataLayer.push({
event: 'insufficient_stock',
product_id: product.id,
product_name: product.name,
requested_quantity: quantity,
available_quantity: stockInfo.quantity
});
alert(`Only ${stockInfo.quantity} available in stock`);
return false;
}
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'add_to_cart',
ecommerce: {
currency: 'USD',
value: product.price * quantity,
items: [{
item_id: product.id,
item_name: product.name,
price: product.price,
quantity: quantity,
stock_status: stockInfo.status,
stock_quantity: stockInfo.quantity,
stock_after_cart: stockInfo.quantity - quantity
}]
}
});
// Track low stock warning
const remainingStock = stockInfo.quantity - quantity;
if (remainingStock > 0 && remainingStock <= stockInfo.lowThreshold) {
dataLayer.push({
event: 'low_stock_trigger',
product_id: product.id,
product_name: product.name,
remaining_quantity: remainingStock,
threshold: stockInfo.lowThreshold
});
}
return true;
}
4. Track Back-in-Stock Notifications
// Track when users sign up for back-in-stock alerts
function trackBackInStockSignup(product, email) {
dataLayer.push({
event: 'back_in_stock_signup',
product_id: product.id,
product_name: product.name,
product_category: product.category,
product_variant: product.variant,
user_email: hashEmail(email), // Hash for privacy
signup_date: new Date().toISOString()
});
// Save to database for later notification
saveBackInStockRequest(product, email);
}
// Form submission handler
document.querySelector('#back-in-stock-form')?.addEventListener('submit', async (e) => {
e.preventDefault();
const email = document.querySelector('#stock-alert-email').value;
const productData = {
id: document.querySelector('[data-product-id]').dataset.productId,
name: document.querySelector('.product-name').textContent,
category: document.querySelector('[data-category]')?.dataset.category,
variant: getSelectedVariant()
};
await trackBackInStockSignup(productData, email);
alert('We\'ll notify you when this item is back in stock!');
});
// Track when back-in-stock notification is sent (server-side)
async function sendBackInStockNotification(productId, userEmail) {
// Send email notification
// Track notification sent
await fetch('/api/analytics/back-in-stock-sent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
product_id: productId,
user_email: userEmail,
sent_date: new Date().toISOString()
})
});
}
// Track conversion from back-in-stock notification
function trackBackInStockPurchase(orderId, productId) {
dataLayer.push({
event: 'back_in_stock_conversion',
transaction_id: orderId,
product_id: productId,
conversion_type: 'back_in_stock_alert'
});
}
5. Track Variant Availability
// Track stock for each product variant
function trackVariantChange(selectedVariant) {
const stockInfo = getStockInfo(selectedVariant.productId, selectedVariant.id);
dataLayer.push({
event: 'variant_selected',
product_id: selectedVariant.productId,
product_name: selectedVariant.productName,
variant_id: selectedVariant.id,
variant_name: selectedVariant.name, // e.g., "Blue / Large"
variant_sku: selectedVariant.sku,
stock_status: stockInfo.status,
stock_quantity: stockInfo.quantity,
price: selectedVariant.price
});
// Update UI based on stock
updateAddToCartButton(stockInfo);
}
// Listen for variant selection changes
document.querySelectorAll('select[name="variant"], input[name="variant"]').forEach(input => {
input.addEventListener('change', (e) => {
const selectedVariant = getSelectedVariantData();
trackVariantChange(selectedVariant);
});
});
6. Real-Time Stock Updates
// Monitor inventory changes in real-time
class InventoryMonitor {
constructor() {
this.checkInterval = 30000; // Check every 30 seconds
this.productId = null;
this.lastStockLevel = null;
}
start(productId) {
this.productId = productId;
this.lastStockLevel = getCurrentStockLevel(productId);
this.intervalId = setInterval(() => {
this.checkStockChanges();
}, this.checkInterval);
}
async checkStockChanges() {
const currentStock = await fetchCurrentStock(this.productId);
if (currentStock !== this.lastStockLevel) {
this.handleStockChange(this.lastStockLevel, currentStock);
this.lastStockLevel = currentStock;
}
}
handleStockChange(oldStock, newStock) {
dataLayer.push({
event: 'inventory_change',
product_id: this.productId,
previous_stock: oldStock,
current_stock: newStock,
stock_delta: newStock - oldStock,
timestamp: new Date().toISOString()
});
// Update UI
updateStockDisplay(newStock);
// Warn if stock decreased
if (newStock < oldStock) {
console.warn(`Stock decreased from ${oldStock} to ${newStock}`);
}
// Alert if now out of stock
if (oldStock > 0 && newStock === 0) {
dataLayer.push({
event: 'stock_depleted',
product_id: this.productId,
depleted_at: new Date().toISOString()
});
alert('This item just went out of stock!');
}
}
stop() {
if (this.intervalId) {
clearInterval(this.intervalId);
}
}
}
// Usage on product page
if (isProductPage()) {
const productId = getProductId();
const monitor = new InventoryMonitor();
monitor.start(productId);
// Stop monitoring when user leaves page
window.addEventListener('beforeunload', () => monitor.stop());
}
7. Server-Side Inventory Event Tracking
// Node.js example - Track inventory events server-side
const express = require('express');
const router = express.Router();
// Track when inventory reaches low stock threshold
router.post('/api/inventory/check-threshold', async (req, res) => {
const { productId, currentStock, threshold } = req.body;
if (currentStock <= threshold) {
// Send to GA4 Measurement Protocol
await sendToGA4({
client_id: 'server',
events: [{
name: 'low_stock_threshold',
params: {
product_id: productId,
current_stock: currentStock,
threshold: threshold,
timestamp: new Date().toISOString()
}
}]
});
// Trigger internal alert
await alertInventoryTeam(productId, currentStock);
}
res.json({ success: true });
});
// Track when product goes out of stock
router.post('/api/inventory/stock-out', async (req, res) => {
const { productId, lastSoldAt } = req.body;
await sendToGA4({
client_id: 'server',
events: [{
name: 'product_stock_out',
params: {
product_id: productId,
last_sold_at: lastSoldAt,
stock_out_at: new Date().toISOString()
}
}]
});
// Get back-in-stock subscribers
const subscribers = await getBackInStockSubscribers(productId);
res.json({
success: true,
subscribers_waiting: subscribers.length
});
});
// Track when product is restocked
router.post('/api/inventory/restock', async (req, res) => {
const { productId, previousStock, newStock } = req.body;
await sendToGA4({
client_id: 'server',
events: [{
name: 'product_restocked',
params: {
product_id: productId,
previous_stock: previousStock,
new_stock: newStock,
stock_added: newStock - previousStock,
restocked_at: new Date().toISOString()
}
}]
});
// Notify subscribers
const subscribers = await getBackInStockSubscribers(productId);
for (const subscriber of subscribers) {
await sendBackInStockEmail(subscriber.email, productId);
}
res.json({
success: true,
notifications_sent: subscribers.length
});
});
async function sendToGA4(data) {
const measurementId = process.env.GA4_MEASUREMENT_ID;
const apiSecret = process.env.GA4_API_SECRET;
await fetch(`https://www.google-analytics.com/mp/collect?measurement_id=${measurementId}&api_secret=${apiSecret}`, {
method: 'POST',
body: JSON.stringify(data)
});
}
module.exports = router;
Platform-Specific Guides
Shopify
<!-- Product page - sections/product-template.liquid -->
<script>
// Get stock information from Shopify
var productStock = {
status: {% if product.available %}'in_stock'{% else %}'out_of_stock'{% endif %},
quantity: {{ product.selected_or_first_available_variant.inventory_quantity | default: 0 }},
policy: '{{ product.selected_or_first_available_variant.inventory_policy }}',
management: '{{ product.selected_or_first_available_variant.inventory_management }}'
};
// Determine stock status
if (productStock.quantity === 0 && productStock.policy === 'continue') {
productStock.status = 'backorder';
} else if (productStock.quantity > 0 && productStock.quantity <= 10) {
productStock.status = 'low_stock';
}
// Track product view with stock info
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'view_item',
ecommerce: {
currency: '{{ cart.currency.iso_code }}',
value: {{ product.price | money_without_currency | remove: ',' }},
items: [{
item_id: '{{ product.selected_or_first_available_variant.sku | default: product.id }}',
item_name: '{{ product.title | escape }}',
item_brand: '{{ product.vendor | escape }}',
item_category: '{{ product.type | escape }}',
item_variant: '{{ product.selected_or_first_available_variant.title | escape }}',
price: {{ product.price | money_without_currency | remove: ',' }},
stock_status: productStock.status,
stock_quantity: productStock.quantity
}]
},
stock_status: productStock.status,
stock_quantity: productStock.quantity
});
// Track variant changes
var variantSelectors = document.querySelectorAll('.product-form__variant-selector');
variantSelectors.forEach(function(selector) {
selector.addEventListener('change', function() {
var selectedVariantId = document.querySelector('[name="id"]').value;
fetch('/products/{{ product.handle }}.js')
.then(res => res.json())
.then(data => {
var variant = data.variants.find(v => v.id == selectedVariantId);
var stockStatus = 'in_stock';
if (!variant.available) {
stockStatus = variant.inventory_policy === 'continue' ? 'backorder' : 'out_of_stock';
} else if (variant.inventory_quantity > 0 && variant.inventory_quantity <= 10) {
stockStatus = 'low_stock';
}
dataLayer.push({
event: 'variant_selected',
variant_id: variant.id,
variant_sku: variant.sku,
variant_name: variant.title,
stock_status: stockStatus,
stock_quantity: variant.inventory_quantity,
price: variant.price / 100
});
});
});
});
// Track out-of-stock attempts
{% unless product.available %}
document.querySelector('.product-form__submit').addEventListener('click', function(e) {
e.preventDefault();
dataLayer.push({
event: 'out_of_stock_attempt',
product_id: '{{ product.id }}',
product_name: '{{ product.title | escape }}',
user_action: 'add_to_cart_attempt'
});
alert('This item is currently out of stock. Sign up for restock notifications!');
});
{% endunless %}
</script>
<!-- Back-in-stock notification form -->
{% unless product.available %}
<div class="back-in-stock-form">
<h3>Get notified when back in stock</h3>
<form id="bis-form">
<input type="email" name="email" placeholder="Your email" required>
<input type="hidden" name="product_id" value="{{ product.id }}">
<input type="hidden" name="variant_id" value="{{ product.selected_or_first_available_variant.id }}">
<button type="submit">Notify Me</button>
</form>
</div>
<script>
document.getElementById('bis-form').addEventListener('submit', async function(e) {
e.preventDefault();
var email = this.querySelector('[name="email"]').value;
var productId = this.querySelector('[name="product_id"]').value;
var variantId = this.querySelector('[name="variant_id"]').value;
// Track signup
dataLayer.push({
event: 'back_in_stock_signup',
product_id: productId,
variant_id: variantId,
product_name: '{{ product.title | escape }}'
});
// Submit to your back-in-stock service
await fetch('/apps/back-in-stock/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, productId, variantId })
});
alert('Thanks! We\'ll email you when this item is back in stock.');
});
</script>
{% endunless %}
WooCommerce
// Add to functions.php or custom plugin
// Include stock status in product view tracking
add_action('woocommerce_after_single_product', function() {
global $product;
$stock_quantity = $product->get_stock_quantity();
$stock_status = $product->get_stock_status(); // 'instock', 'outofstock', 'onbackorder'
// Determine detailed stock status
$detailed_status = $stock_status;
if ($stock_status === 'instock' && $stock_quantity <= 10 && $stock_quantity > 0) {
$detailed_status = 'low_stock';
}
?>
<script>
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'view_item',
ecommerce: {
currency: '<?php echo get_woocommerce_currency(); ?>',
value: <?php echo $product->get_price(); ?>,
items: [{
item_id: '<?php echo $product->get_sku() ?: $product->get_id(); ?>',
item_name: '<?php echo esc_js($product->get_name()); ?>',
price: <?php echo $product->get_price(); ?>,
stock_status: '<?php echo $detailed_status; ?>',
stock_quantity: <?php echo $stock_quantity ?? 0; ?>,
backorders_allowed: <?php echo $product->backorders_allowed() ? 'true' : 'false'; ?>
}]
},
stock_status: '<?php echo $detailed_status; ?>',
stock_quantity: <?php echo $stock_quantity ?? 0; ?>
});
</script>
<?php
});
// Track out-of-stock product views
add_action('wp_footer', function() {
if (is_product()) {
global $product;
if (!$product->is_in_stock()) {
?>
<script>
dataLayer.push({
event: 'out_of_stock_view',
product_id: '<?php echo $product->get_id(); ?>',
product_name: '<?php echo esc_js($product->get_name()); ?>',
stock_status: '<?php echo $product->get_stock_status(); ?>'
});
// Track add to cart attempts on out-of-stock products
document.querySelector('.single_add_to_cart_button')?.addEventListener('click', function(e) {
<?php if (!$product->is_in_stock() && !$product->backorders_allowed()): ?>
e.preventDefault();
dataLayer.push({
event: 'out_of_stock_attempt',
product_id: '<?php echo $product->get_id(); ?>',
product_name: '<?php echo esc_js($product->get_name()); ?>'
});
alert('This product is currently out of stock.');
<?php endif; ?>
});
</script>
<?php
}
}
});
// Track low stock threshold alerts (run via cron)
add_action('woocommerce_low_stock', function($product) {
// Log to analytics
error_log('Low stock alert: ' . $product->get_name());
// Send to GA4 via Measurement Protocol
$data = [
'client_id' => 'server',
'events' => [[
'name' => 'low_stock_threshold',
'params' => [
'product_id' => $product->get_id(),
'product_name' => $product->get_name(),
'stock_quantity' => $product->get_stock_quantity(),
'threshold' => get_option('woocommerce_notify_low_stock_amount')
]
]]
];
wp_remote_post('https://www.google-analytics.com/mp/collect?measurement_id=' . GA4_MEASUREMENT_ID . '&api_secret=' . GA4_API_SECRET, [
'body' => json_encode($data),
'headers' => ['Content-Type' => 'application/json']
]);
});
// Track when product goes out of stock
add_action('woocommerce_no_stock', function($product) {
$data = [
'client_id' => 'server',
'events' => [[
'name' => 'product_stock_out',
'params' => [
'product_id' => $product->get_id(),
'product_name' => $product->get_name(),
'stock_out_at' => current_time('mysql')
]
]]
];
wp_remote_post('https://www.google-analytics.com/mp/collect?measurement_id=' . GA4_MEASUREMENT_ID . '&api_secret=' . GA4_API_SECRET, [
'body' => json_encode($data),
'headers' => ['Content-Type' => 'application/json']
]);
});
BigCommerce
// Add to theme/assets/js/theme/product.js
import PageManager from './page-manager';
import utils from '@bigcommerce/stencil-utils';
export default class Product extends PageManager {
onReady() {
this.trackProductStock();
this.monitorStockChanges();
}
trackProductStock() {
utils.api.product.getById(this.context.productId, { template: 'products/product-view' }, (err, response) => {
if (response) {
const $response = $(response);
const stockLevel = parseInt($response.find('[data-stock-level]').data('stockLevel'));
const stockStatus = this.getStockStatus(stockLevel);
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'view_item',
ecommerce: {
items: [{
item_id: this.context.productId,
stock_status: stockStatus,
stock_quantity: stockLevel
}]
},
stock_status: stockStatus,
stock_quantity: stockLevel
});
}
});
}
getStockStatus(quantity) {
if (quantity === 0) return 'out_of_stock';
if (quantity <= 10) return 'low_stock';
return 'in_stock';
}
monitorStockChanges() {
$('[data-product-option-change]').on('change', (event) => {
utils.api.productAttributes.optionChange(this.context.productId, $(event.target).serialize(), (err, response) => {
if (response) {
const stockLevel = response.data.stock;
const stockStatus = this.getStockStatus(stockLevel);
dataLayer.push({
event: 'variant_selected',
product_id: this.context.productId,
stock_status: stockStatus,
stock_quantity: stockLevel
});
}
});
});
}
}
Magento
<!-- Add to Magento_Catalog/templates/product/view.phtml -->
<?php
$_product = $block->getProduct();
$stockItem = $_product->getExtensionAttributes()->getStockItem();
$stockQty = $stockItem->getQty();
$isInStock = $stockItem->getIsInStock();
$stockStatus = 'out_of_stock';
if ($isInStock) {
$stockStatus = $stockQty <= 10 ? 'low_stock' : 'in_stock';
}
?>
<script>
require(['jquery'], function($) {
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'view_item',
ecommerce: {
currency: '<?php echo $block->getCurrency(); ?>',
value: <?php echo $_product->getFinalPrice(); ?>,
items: [{
item_id: '<?php echo $_product->getSku(); ?>',
item_name: '<?php echo $block->escapeJs($_product->getName()); ?>',
price: <?php echo $_product->getFinalPrice(); ?>,
stock_status: '<?php echo $stockStatus; ?>',
stock_quantity: <?php echo (int)$stockQty; ?>
}]
},
stock_status: '<?php echo $stockStatus; ?>',
stock_quantity: <?php echo (int)$stockQty; ?>
});
<?php if (!$isInStock): ?>
// Track out-of-stock product view
dataLayer.push({
event: 'out_of_stock_view',
product_id: '<?php echo $_product->getId(); ?>',
product_name: '<?php echo $block->escapeJs($_product->getName()); ?>'
});
<?php endif; ?>
});
</script>
Testing & Validation
Stock Tracking Checklist
- Product Views:
view_itemincludesstock_statusandstock_quantity - Variant Changes: Stock updates when variant selected
- Out-of-Stock Views: Custom event fires for unavailable products
- Add to Cart: Stock checked before adding to cart
- Low Stock Alerts: Tracked when inventory crosses threshold
- Back-in-Stock: Signup events tracked properly
- Stock Status Values: Consistent naming (in_stock, out_of_stock, low_stock, backorder)
- Real-Time Updates: Stock changes reflected in analytics
GA4 Custom Dimensions Setup
Create these custom dimensions in GA4:
stock_status (Event-scoped)
- Description: Product stock status
- Values: in_stock, out_of_stock, low_stock, backorder
stock_quantity (Event-scoped)
- Description: Current stock level
- Type: Number
stock_after_cart (Event-scoped)
- Description: Remaining stock after add to cart
- Type: Number
Console Validation
// Check if stock tracking is working
function validateStockTracking() {
const viewItems = dataLayer.filter(e => e.event === 'view_item');
const latestView = viewItems[viewItems.length - 1];
console.log('Stock Tracking Validation:\n');
if (!latestView) {
console.error('✗ No view_item events found');
return;
}
const item = latestView.ecommerce?.items?.[0];
console.log('Stock Status:', item?.stock_status || '⚠️ MISSING');
console.log('Stock Quantity:', item?.stock_quantity ?? '⚠️ MISSING');
if (!item?.stock_status) {
console.error('✗ Missing stock_status parameter');
} else {
console.log('✓ Stock status tracked');
}
if (typeof item?.stock_quantity === 'undefined') {
console.error('✗ Missing stock_quantity parameter');
} else {
console.log('✓ Stock quantity tracked');
}
// Check for stock-related events
const stockEvents = dataLayer.filter(e =>
['out_of_stock_attempt', 'low_stock_trigger', 'back_in_stock_signup'].includes(e.event)
);
console.log(`\nStock Events Found: ${stockEvents.length}`);
stockEvents.forEach(e => console.log(`- ${e.event}`));
}
validateStockTracking();