Skip to main content
How-to

Analytics Event Hooks

Analytics hooks let you intercept and modify event payloads before they are sent to third-party platforms like GA4, Klaviyo, Facebook, and others. Use them to add custom properties, enrich events with business-specific data, or adjust values — without modifying runtime code.

note

This functionality is currently available in the StoreFront BETA runtime. If you would like to use this functionality, please contact support so your runtime can be set to use the BETA.


Merchant Debug Logging

When you are logged into the UltraCart admin panel and viewing your storefront, every analytics event is automatically logged to the browser console. This is the fastest way to see what data is being sent to each platform.

How to use it

  1. Log in to your UltraCart admin panel

  2. Navigate to your StoreFront and click browse to open it

  3. Open your browser's Developer Tools (F12 or right-click > Inspect)

  4. Switch to the Console tab

  5. Browse your store — add items to cart, view products, start checkout

You will see collapsed log groups like:

▸ [Analytics] GA4 → add_to_cart
▸ [Analytics] Klaviyo → Added to Cart
▸ [Analytics] Converge → Added To Cart

Click any group to expand it and see the full JSON payload that was sent to that platform. This shows you the exact data each vendor received, making it easy to verify your hooks are working or to understand the payload structure before writing a hook.

info

This logging only appears when you are logged in as a merchant. Shoppers never see it.


Quick Start

Add this to your StoreFronts custom JavaScript at the top of the Privacy & Tracking → Customer → Tracking / Conversion depending upon where the event is firing:

window.sfvbGa4AddToCartHook = function(cart, event) {
// Add a custom parameter to every GA4 add_to_cart event
event.custom_source = "storefront";
return event;
};

That's it. When a shopper adds an item to cart, the GA4 add_to_cart event will now include custom_source: "storefront". Use the merchant debug logging (above) to verify your custom property appears in the payload.


How Hooks Work

Every hook has the same signature:

window.sfvb{Vendor}{EventName}Hook = function(cart, event) {

| Hook Name | GA4 Event | When It Fires |
| --- | --- | --- |
| `sfvbGa4AddToCartHook` | `add_to_cart` | Item added to cart |
| `sfvbGa4RemoveFromCartHook` | `remove_from_cart` | Item removed from cart |
| `sfvbGa4ViewItemHook` | `view_item` | Product page viewed |
| `sfvbGa4ViewItemListHook` | `view_item_list` | Product list/collection viewed |
| `sfvbGa4ViewCartHook` | `view_cart` | Cart page viewed |
| `sfvbGa4AddToWishlistHook` | `add_to_wishlist` | Item added to wishlist |
| `sfvbGa4LoginHook` | `login` | Customer logs in |
| `sfvbGa4SignupHook` | `signup` | Customer registers |
| `sfvbGa4SearchHook` | `search` | Site search performed |
| `sfvbGa4AddPaymentInfoHook` | `add_payment_info` | Payment info entered at checkout |
| `sfvbGa4AddShippingInfoHook` | `add_shipping_info` | Shipping address completed |
| `sfvbGa4BeginCheckoutHook` | `begin_checkout` | Checkout process started |
| `sfvbGa4SelectPromotionHook` | `select_promotion` | Upsell/promotion selected |
| `sfvbGa4ViewPromotionHook` | `view_promotion` | Upsell/promotion viewed |

### Klaviyo

| Hook Name | Klaviyo Event | When It Fires |
| --- | --- | --- |
| `sfvbKlaviyoViewItemHook` | `Viewed Product` | Product page viewed |
| `sfvbKlaviyoAddToCartHook` | `Added to Cart` | Item added to cart (fires per item) |
| `sfvbKlaviyoInitiateCheckoutHook` | `Started Checkout` | Checkout process started |

### Retention (GEQ)

| Hook Name | Retention Event | When It Fires |
| --- | --- | --- |
| `sfvbRetentionViewItemHook` | `Viewed Product Reclaim` | Product page viewed |
| `sfvbRetentionAddToCartHook` | `addToCart` | Item added to cart (fires per item) |
| `sfvbRetentionInitiateCheckoutHook` | `Checkout Started Reclaim` | Checkout process started |

### Pinterest

| Hook Name | Pinterest Event | When It Fires |
| --- | --- | --- |
| `sfvbPinterestAddToCartHook` | `addtocart` | Item added to cart |

### TikTok

| Hook Name | TikTok Event | When It Fires |
| --- | --- | --- |
| `sfvbTikTokAddToCartHook` | `AddToCart` | Item added to cart (fires per item) |
| `sfvbTikTokAddPaymentInfoHook` | `AddPaymentInfo` | Payment info entered at checkout |
| `sfvbTikTokInitiateCheckoutHook` | `InitiateCheckout` | Checkout process started |

### Converge

| Hook Name | Converge Event | When It Fires |
| --- | --- | --- |
| `sfvbCvgViewItemHook` | `Viewed Product` | Product page viewed |
| `sfvbCvgViewItemListHook` | `Viewed Collection` | Product list/collection viewed |
| `sfvbCvgViewCartHook` | `Viewed Collection` (cart) | Cart page viewed |
| `sfvbCvgAddToCartHook` | `Added To Cart` | Item added to cart (fires per item) |
| `sfvbCvgRemoveFromCartHook` | `Removed From Cart` | Item removed from cart |
| `sfvbCvgBeginCheckoutHook` | `Started Checkout` | Checkout process started |
| `sfvbCvgAddPaymentInfoHook` | `Added Payment Info` | Payment info entered at checkout |

### Facebook Pixel

These hooks apply to events from the UltraCart Analytics Manager. Payloads use Facebook's event format (`content_ids`, `content_name`, `content_type`).

| Hook Name | Facebook Event | When It Fires |
| --- | --- | --- |
| `sfvbFacebookAddPaymentInfoHook` | `AddPaymentInfo` | Payment info entered at checkout |
| `sfvbFacebookAddToCartHook` | `AddToCart` | Item added to cart |
| `sfvbFacebookAddToWishlistHook` | `AddToWishlist` | Item added to wishlist |
| `sfvbFacebookCompleteRegistrationHook` | `CompleteRegistration` | Customer registers |
| `sfvbFacebookInitiateCheckoutHook` | `InitiateCheckout` | Checkout process started |
| `sfvbFacebookLeadHook` | `Lead` | Lead captured |
| `sfvbFacebookSearchHook` | `Search` | Site search performed |
| `sfvbFacebookViewContentHook` | `ViewContent` | Product/content viewed |

### Bing Ads

These hooks apply to events from the UltraCart Analytics Manager. Payloads use Bing UET format (`ec`, `ea`, `el`, `ev`).

| Hook Name | Bing Event | When It Fires |
| --- | --- | --- |
| `sfvbBingAddPaymentInfoHook` | `AddPaymentInfo` | Payment info entered at checkout |
| `sfvbBingAddToCartHook` | `AddToCart` | Item added to cart |

| Property | Description |
| --- | --- |
| `cart.cartId` | Unique cart identifier |
| `cart.email` | Customer email (if provided) |
| `cart.currencyCode` | Currency code (e.g., "USD") |
| `cart.total` | Order total |
| `cart.subtotalWithDiscount` | Subtotal after discounts |
| `cart.items` | Array of item objects |
| `cart.items[].itemId` | Item ID |
| `cart.items[].description` | Item description |
| `cart.items[].quantity` | Quantity |
| `cart.items[].unitCost` | Unit price |
| `cart.items[].totalCostWithDiscount` | Line total after discount |
| `cart.items[].autoOrderFirstRebillDate` | Subscription rebill date (if subscription) |
| `cart.coupon` | Applied coupon code |
| `cart.customField1` - `cart.customField10` | Custom fields |
| `cart.shipToFirstName`, `shipToLastName`, etc. | Shipping address |
| `cart.billToFirstName`, `billToLastName`, etc. | Billing address |
| * * *<br>## Examples<br>### Add hashed email to GA4 checkout events<br>```js window.sfvbGa4BeginCheckoutHook = function(cart, event) { if (cart.email) { event.user_email_sha256 = window.sfvbSha256Sync(cart.email); } return event; }; ```<br>### Infer subscription type from item ID patterns<br>```js window.sfvbGa4AddToCartHook = function(cart, event) { for (var i = 0; i < event.items.length; i++) { var item = event.items[i]; var itemId = item.item_id;<br>if (itemId.indexOf("LYP") === 0) { item.item_category = "subscription"; item.item_category2 = "monthly";<br>if (itemId.indexOf("6") >= 0) { item.item_variant = "6-bottle"; } else if (itemId.indexOf("3") >= 0) { item.item_variant = "3-bottle"; } else { item.item_variant = "1-bottle"; } } } return event; }; ```<br>### Add referral source to Klaviyo events<br>```js window.sfvbKlaviyoAddToCartHook = function(cart, event) { var urlParams = new URLSearchParams(window.location.search); var ref = urlParams.get("ref"); if (ref) { event.ReferralSource = ref; }<br>if (event.AddedItemProductID && event.AddedItemProductID.indexOf("SUB") === 0) { event.IsSubscription = true; }<br>return event; }; ```<br>### Enrich Converge payloads with customer segment<br>```js window.sfvbCvgAddToCartHook = function(cart, payload) { if (cart.customField1) { payload.profileProperties = payload.profileProperties | |
| payload.profileProperties.customer_segment = cart.customField1; }<br>if (payload.properties && payload.properties.product_id) { payload.properties.brand = "My Brand"; }<br>return payload; }; ```<br>### Enrich Facebook Pixel events<br>```js window.sfvbFacebookAddToCartHook = function(cart, data) { if (!data.currency && cart.currencyCode) { data.currency = cart.currencyCode; }<br>if (cart.customField1) { data.content_category = cart.customField1; }<br>return data; }; ```<br>### Apply the same enrichment across multiple vendors<br>```js // Shared helper function enrichWithSubscriptionInfo(items, itemIdField) { itemIdField = itemIdField | |

for (var i = 0; i < items.length; i++) {
var id = items[i][itemIdField];
if (id && id.indexOf("LYP") === 0) {
items[i].subscription_type = "monthly";
}
}
}

// GA4
window.sfvbGa4AddToCartHook = function(cart, event) {
enrichWithSubscriptionInfo(event.items, "item_id");
return event;
};

// Klaviyo
window.sfvbKlaviyoAddToCartHook = function(cart, event) {
if (event.AddedItemProductID && event.AddedItemProductID.indexOf("LYP") === 0) {
event.SubscriptionType = "monthly";
}
return event;
};

// Converge
window.sfvbCvgAddToCartHook = function(cart, payload) {
if (payload.properties && payload.properties.product_id) {
var id = payload.properties.product_id;
if (id.indexOf("LYP") === 0) {
payload.properties.subscription_type = "monthly";
}
}
return payload;
};

Best Practices

  1. Always return the event (or mutate in place and let the fallback handle it).

  2. Keep hooks lightweight — they run synchronously before each dispatch.

  3. Don't remove required fields — vendors may reject events missing required properties. Add properties; avoid deleting existing ones.

  4. Use the merchant debug logging to verify your hooks. Log in to admin, view your storefront, open DevTools, and confirm your custom properties appear in the payload.

  5. Use GA4 DebugView to verify custom parameters appear correctly in Google Analytics.

  6. Test in browser console first — define your hook function directly in the console, trigger the action, and check the logged output before committing to your theme scripts.

Was this page helpful?