Marketing Attribution Apps
Marketing attribution apps enable marketing attribution platforms to attribute orders across all commerce channels — storefront, campaigns, Admin API, and subscription renewals — back to the ads and campaigns that drove them.
To provide full attribution coverage, apps need to handle two complementary flows:
- Storefront Order Attribution — Use Event Tracking and the GraphQL Storefront API to capture platform-specific identifiers from the visitor's browser and store them as attribution metadata on the cart.
- Campaigns & API Order Attribution — Subscribe to Webhooks to receive order events server-side and extract the stored attribution metadata for conversion tracking.
Attribution Flow Overview
Storefront Order Attribution
Storefront order attribution runs in the visitor's browser via an Event Tracker installed through your app's manifest. The event tracker needs to do three things:
- Capture platform identifiers from browser cookies and URL parameters.
- Store identifiers as cart attribution metadata using the GraphQL Storefront API so they persist through to the completed order.
- Fire client-side pixel events by subscribing to Storefront Events for real-time browser-side tracking.
App Setup
Getting Started with Apps
If you haven't already, create your app on Next Commerce Accounts and install App Kit to build and push your app files.
Your app's manifest defines the storefront integration. Map a javascript file as the storefront_event_tracker, use settings_schema to allow merchants to configure platform-specific IDs, and add an App Snippet to inject the ad platform's pixel script into the storefront.
{
"storefront_event_tracker": "tracking.js",
"settings_schema": [
{
"name": "pixel_id",
"type": "text",
"label": "Pixel ID",
"default": "",
"required": 1,
"help_text": "Your ad platform pixel identifier.",
"max_length": 250
}
],
"locations": {
"storefront": {
"global_header": "snippets/global_header.html"
}
}
}Manage Settings via API
Apps can programmatically manage the merchant's settings values (e.g. Pixel ID) through the appsSettingsUpdate Admin API endpoint, allowing you to populate configuration from your own app dashboard.
The global_header snippet is where you load the ad platform's pixel script so that it sets the necessary browser cookies. The event tracker then reads these cookies and stores them on the cart.
{% if app.settings.pixel_id %}
<script async src="https://platform.example.com/pixel.js?id={{ app.settings.pixel_id }}"></script>
{% endif %}Event Tracker
When your app is installed, the event tracker is automatically created with the content of tracking.js. The merchant's settings are accessible via app.settings and the GraphQL Storefront API is available at /api/graphql/.
Below is an example event tracker that captures platform identifiers, stores them as cart attribution metadata via the createCart and updateCartAttribution GraphQL mutations, and subscribes to storefront events for client-side pixel tracking.
Cookie Timing
Ad platform pixel scripts set cookies asynchronously after page load. Your event tracker should wait for the relevant cookies to be set before attempting to read them. A timeout of ~5 seconds is typically sufficient.
if (app.settings.pixel_id) {
// --- Helpers ---
function getCookie(name) {
return document.cookie
.split(";")
.find(c => c.trim().startsWith(`${name}=`))
?.split("=")[1];
}
function waitForCookie(name, timeout = 5000, interval = 500) {
return new Promise((resolve, reject) => {
const start = Date.now();
const check = setInterval(() => {
if (getCookie(name)) {
clearInterval(check);
resolve(getCookie(name));
} else if (Date.now() - start >= timeout) {
clearInterval(check);
reject(new Error(`Timeout waiting for cookie: ${name}`));
}
}, interval);
});
}
function queryGraphql(query, variables = {}) {
return fetch("/api/graphql/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, variables })
}).then(r => r.json());
}
// --- GraphQL Mutations ---
const CREATE_CART = `mutation createCart {
createCart(input: {}) {
success
errors
cart { id, pk, attribution { metadata } }
}
}`;
const UPDATE_CART_ATTRIBUTION = `mutation updateCartAttrMetadata(
$cartId: String, $metadata: GenericScalar
) {
updateCartAttribution(
input: {cartId: $cartId, attribution: {metadata: $metadata}}
) {
success
errors
cart { id, pk, attribution { metadata } }
}
}`;
// --- Attribution Capture ---
async function captureAttribution() {
// 1. Create a cart
const cartData = await queryGraphql(CREATE_CART);
const cart = cartData.data?.createCart?.cart;
if (!cart) return;
// 2. Wait for ad platform cookies to be set
try {
await waitForCookie("your_cookie_name");
} catch (e) {
console.error(e);
}
// 3. Capture identifiers and store as cart attribution metadata
const metadata = cart.attribution?.metadata || {};
const browserId = getCookie("your_cookie_name");
const clickId = getCookie("your_click_cookie_name");
if (browserId) metadata.your_browser_id = browserId;
if (clickId) metadata.your_click_id = clickId;
metadata.pixel_id = app.settings.pixel_id;
await queryGraphql(UPDATE_CART_ATTRIBUTION, {
cartId: cart.id,
metadata: metadata
});
}
captureAttribution();
// --- Client-Side Pixel Events ---
analytics.subscribe("page_viewed", event => {
// Fire page view event on your ad platform
});
analytics.subscribe("product_viewed", event => {
// Fire view content event with event.data product details
});
analytics.subscribe("product_added_to_cart", event => {
// Fire add to cart event with event.data line item details
});
analytics.subscribe("checkout_started", event => {
// Fire initiate checkout event with event.data cart details
});
analytics.subscribe("checkout_completed", event => {
// Fire purchase/conversion event with event.data order details
});
}See Storefront Event Tracking for the full list of available events and their data structures.
Attribution Metadata Persists to Orders
Attribution metadata stored on the cart is automatically carried over to the order when the customer completes checkout. This is what makes the webhook-based conversion flow possible — the identifiers captured in the browser are available in the order.created webhook payload.
Campaigns & API Order Attribution
Not all orders originate from the storefront. Orders created through Campaigns, the Admin API, and recurring Subscription renewals bypass the storefront entirely — Webhooks are the way to capture attribution data for these conversions.
Subscribe to Webhooks
Subscribe to the order.created webhook event using the webhooksCreate Admin API endpoint. Your app should do this during the OAuth installation flow. Always verify the webhook signature before processing incoming events.
{
"target": "https://your-app.example.com/webhooks/",
"events": ["order.created"],
"signing_secret": "your-signing-secret"
}Extract Attribution Metadata from Order
The order.created webhook payload contains the full order data, including the attribution object with the metadata your event tracker stored on the cart.
{
"event_type": "order.created",
"object": "order",
"data": {
...
"number": "109659",
"source": "storefront",
"total_incl_tax": "84.98",
"total_excl_tax": "84.98",
"currency": "USD",
"reporting_values": {
"currency": "USD",
"total_incl_tax": "84.98",
"total_excl_tax": "84.98",
"shipping_incl_tax": "4.99",
"shipping_excl_tax": "4.99",
"total_discount": "0.00"
},
"attribution": {
...
"metadata": {
"your_platform_id": "your_value",
"your_click_id": "your_value",
"your_browser_id": "your_value"
}
},
...
}
}View the full order.created webhook payload for all available fields including user, lines, shipping address, and transaction data.