Event tracking with Headless (Shopify Hydrogen)
Event tracking with Headless (Shopify Hydrogen)
It’s crucial that you track touchpoints to analyze storefront performance, create reports, and power Coveo Machine Learning (Coveo ML) models. You can do this by sending events to the Coveo Usage Analytics (Coveo UA) service.
If you use Coveo Headless to build your product discovery solutions, track events using dedicated Headless controllers. These controllers automatically log specific commerce events, such as when a user makes a purchase or adds a product to a cart.
Headless commerce controllers rely on the Event Protocol to log events.
The following table shows the types of events to track and the corresponding controllers.
Purchase events
Purchase events can be tracked automatically by leveraging the Coveo app, which logs purchase events when the required cart attributes are set:
-
coveoClientId
-
coveoTrackingId
-
coveoOrganizationId
-
coveoAccessToken
Add the attributes to your cart
by performing the following series of modifications to your underlying Shopify cart logic.
|
Note
If you’re not using the app, see implement your own web pixel for instructions on how to log purchase events. |
Prerequisites
Be familiar with the concepts discussed in Getting started (Shopify Hydrogen) and Core concepts (Shopify Hydrogen).
Implementation
|
Note
Samples in this section are simplified for clarity.
For a complete implementation, see |
The example implementation consists of two main parts, a helper function to update cart attributes and the usage of this helper in both the Remix action
and Remix loader
.
Create a helper function to update the cart
Check if the attributes are present on the cart, and if not, add them using the updateAttributes
method from the Cart
handler.
You’ll call this after any operation that retrieves or modifies the cart to configure the attributes as required for proper purchase event tracking.
// ...
import { engineConfig, engineDefinition } from '~/lib/coveo.engine';
// ...
async function setCoveoConfigAttributes(
context: any,
request: Request,
cartResult: CartQueryDataReturn,
) {
const {cart: cartHandler} = context;
const cart = cartResult.cart;
if (!cart) return cartResult;
const attributes = cart.attributes ?? [];
const attributesToUpdate = [];
const navigatorProvider = new ServerSideNavigatorContextProvider(request);
const {clientId} = navigatorProvider;
const {
configuration: {
analytics: {trackingId},
organizationId,
accessToken,
},
} = engineConfig;
const attributesToFind = [
'coveoClientId',
'coveoTrackingId',
'coveoOrganizationId',
'coveoAccessToken',
];
const foundAttributes = (cart.attributes ?? []).reduce((acc, item) => {
if (attributesToFind.includes(item.key)) {
acc[item.key] = {key: item.key, value: item.value};
}
return acc;
}, {} as Record<string, {key: string; value: string}>);
if (!foundAttributes.coveoClientId) {
attributesToUpdate.push({key: 'coveoClientId', value: clientId});
}
if (!foundAttributes.coveoTrackingId) {
attributesToUpdate.push({key: 'coveoTrackingId', value: trackingId});
}
if (!foundAttributes.coveoOrganizationId) {
attributesToUpdate.push({
key: 'coveoOrganizationId',
value: organizationId,
});
}
if (!foundAttributes.coveoAccessToken) {
attributesToUpdate.push({key: 'coveoAccessToken', value: accessToken});
}
let updatedResult = cartResult;
if (attributesToUpdate.length > 0) {
try {
updatedResult = await cartHandler.updateAttributes(attributesToUpdate);
} catch (error) {
console.warn('Failed to set Coveo attributes:', error);
}
}
return updatedResult;
}
Use the ServerSideNavigatorContextProvider to obtain the clientId for the current session or visitor.
For more details on how the ServerSideNavigatorContextProvider works and its implementation, see Server-side and client navigation context providers. |
|
Add the attributes to the list of attributes to update if they’re not already present. | |
Update the cart attributes using the updateAttributes method from the Cart handler. |
Update the cart attributes
Use your helper function when the cart is retrieved and modified.
-
Loader
: on page load to ensure attributes are set when the cart is retrieved.export async function loader({request, context}: LoaderFunctionArgs) { const {cart} = context; // ... const cartData = await cart.get();
if (cartData) { await setCoveoConfigAttributes(context, request, {cart: cartData});
} // ... }
Fetches the current cart data from Shopify when the page loads or is refreshed. Add the required Coveo cart attributes if they’re missing, so purchase events can be tracked correctly. -
Action
: after any calls that would modify the cart. (for example, adding or removing items)export async function action({request, context}: ActionFunctionArgs) { const {cart} = context; // ... result = await setCoveoConfigAttributes(context, request, result);
const {cart: cartResult, errors, warnings} = result; return json( { cart: cartResult, errors, warnings, analytics: { cartId, }, }, {status, headers}, ); }
Add the required Coveo cart attributes after any cart mutation. This is essential for accurate purchase event tracking by the Coveo app web pixel.
By setting the, coveoCoveoClientId
, coveoTrackingId
, coveoOrganizationId
and coveoAccessToken
attributes on the cart, the Coveo app web pixel can automatically log purchase events when a transaction is completed.
This integration streamlines event tracking and analytics for your Shopify with Headless and Hydrogen commerce solution.