Shopify Pixel Instrumentation

Shopify Pixel Instrumentation uses Shopify Web Pixels to capture customer interaction events directly from Shopify’s Customer Events framework. This approach provides a developer-driven implementation model where each event is explicitly defined, mapped, and transmitted to Algonomy rCDP.

Unlike No-Code Instrumentation, which automatically captures standard events, Pixel Instrumentation enables you to implement custom tracking logic, enrich payloads with additional metadata, and control how events are structured and delivered to rCDP.

Note: This approach is best suited for advanced implementations where precise control over event data is required.

Manual Integration Approach

The Shopify Pixel approach gives full control over event implementation. Each event must be explicitly subscribed, processed, and sent to rCDP.

Unlike auto-capture integrations, developers define how each event is handled, including payload transformation and mapping logic.

When to Use Pixel Integration

  • You require precise control over event payloads

  • Your implementation requires custom tracking logic

  • You need Shopify-specific event handling

Tip: For standard clickstream tracking, use No-Code Instrumentation for faster setup and lower maintenance.

How It Works

Customer Action → Shopify Event Bus → Pixel Code Subscribes → Transform / Map Payload → Send to rCDP

Shopify Web Pixels execute JavaScript within a sandboxed iframe environment. Your pixel code listens to Shopify’s event bus, processes event data, and sends structured payloads to Algonomy rCDP using the SDK.

Note: Pixel execution is event-driven and runs only when subscribed Shopify events are triggered.

Development Lifecycle in Shopify

  1. Pixel code is written in Shopify’s Custom Pixel editor

  2. Testing and debugging occur within Shopify

  3. Deployment is managed via Shopify pixel tools

Note: Pixel code is not managed in the rCDP portal.

Creating a Custom Pixel in Shopify

  1. Log into Shopify as Admin at: https://your-store.myshopify.com/admin.

  2. Navigate to Settings > Customer events.

  3. Click Add Custom Pixel.

  4. The Pixel Code editor is displayed.

  5. Paste your integration code in the Pixel Code editor.

  6. Provide a meaningful name for your Pixel such as "Algonomy Pixel".

  7. Add the Algonomy SDK loader and event subscriptions.

  8. Click Connect to activate the pixel.

  9. Verify the connection, go to Settings > Customer events, the Algonomy Pixel is shown as Connected.

Tip: Once connected, the pixel runs automatically across the storefront.

Loading Algonomy rCDP SDK

The Algonomy rCDP Clickstream JS SDK provides the core runtime required to process and send events to Algonomy rCDP. It exposes the required event execution methods used by the pixel code, standardizes event payloads according to the rCDP schema, and manages communication with the rCDP platform.

The SDK is loaded asynchronously by dynamically injecting the SDK script into the page. The loader creates a <script> element using the tenant and site configuration values, appends it to the document head, and initializes the SDK once the script finishes loading. This approach prevents duplicate script injection and ensures the SDK loads only once across the pixel runtime. Events triggered before the SDK is ready are queued and executed after the SDK initialization completes, ensuring that no events are lost during page load.

To load Algonomy rCDP Clickstream JS SDK:

  1. Download or copy the Algonomy rCDP Clickstream JS SDK available here.

  2. Before deploying, replace the following placeholders with values provided during onboarding:

<TENANT_HASH>
<SITE_HASH>
			
  1. Paste the code at the top of your Custom Pixel code editor, and load the Algonomy SDK.

This loader ensures:

  • The SDK loads asynchronously

  • Events are queued until the SDK is ready

  • Duplicate SDK injection is prevented

Global Configuration Example

const ALGONOMY = {
DEBUG: true,
TENANT_HASH: "<TENANT_HASH>",
SITE_HASH: "<SITE_HASH>",
REGION: {
JS_URL: "https://rcdp-us.algonomy.com",
API_URL: "https://sandbox.algonomy.com"
},
get SCRIPT_URL() {
return `${this.REGION.JS_URL}/js/${this.TENANT_HASH}/${this.SITE_HASH}.js`;
}
};
			

Supporting Utilities

The pixel integration includes utility components for debugging, performance monitoring, and safe SDK initialization. These utilities ensure reliable SDK loading and provide visibility into event execution.

Debug Logger

The Debug Logger provides structured console logging during development. When debugging is enabled, it outputs logs for SDK loading, event execution, and errors.

function algonomyLog(level, message, data) {
if (!ALGONOMY.DEBUG) return;
const prefix = "[Algonomy Pixel]";
switch (level) {
case "error": console.error(prefix, message, data || ""); break;
case "warn": console.warn(prefix, message, data || ""); break;
default: console.log(prefix, message, data || "");
}
}
			

Tip: Disable DEBUG in production to avoid unnecessary console logs.

Performance Metrics

Performance Metrics track SDK loading time and event execution latency. This helps monitor performance impact and debug slow event handling.

const AlgonomyPerf = {
sdkStart: 0, sdkEnd: 0,
markSDKStart() { this.sdkStart = performance.now(); },
markSDKEnd() {
this.sdkEnd = performance.now();
algonomyLog("log", `SDK Loaded in ${(this.sdkEnd - this.sdkStart).toFixed(2)} ms`);
},
measureEvent(eventName, fn) {
const start = performance.now();
fn();
const end = performance.now();
algonomyLog("log", `${eventName} executed in ${(end - start).toFixed(2)} ms`);
}
};
			

Note: Performance metrics are logged only when DEBUG mode is enabled.

Singleton SDK Loader

The Singleton Loader ensures that the SDK loads only once within the Shopify pixel environment. It also queues events until the SDK is ready.

if (!window.__algonomyLoader) {
window.__algonomyLoader = {
loaded: false,
loading: false,
customerSet: false,
queue: []
};
}

function loadAlgonomy(callback) {
const loader = window.__algonomyLoader;
if (typeof callback === "function") loader.queue.push(callback);

if (loader.loaded) { flushQueue(); return; }
if (loader.loading) return;

loader.loading = true;
AlgonomyPerf.markSDKStart();

if (!document.querySelector("script[data-algonomy]")) {
const script = document.createElement("script");
script.src = ALGONOMY.SCRIPT_URL;
script.async = true;
script.setAttribute("data-algonomy", "true");

script.onload = waitForReady;
script.onerror = function () {
loader.loading = false;
algonomyLog("error", "SDK failed to load");
};

document.head.appendChild(script);
} else {
waitForReady();
}

function waitForReady() {
const interval = setInterval(() => {
if (window.rcdp && typeof rcdp.executeEventByData === "function") {
clearInterval(interval);

loader.loaded = true;
loader.loading = false;

AlgonomyPerf.markSDKEnd();

if (ALGONOMY.DEBUG) {
console.log("%cAlgonomy Pixel Loaded",
"background:#111;color:#00ff99;padding:4px 8px;border-radius:4px;");
}

setCustomerIfExists();
cacheBasePayload();
flushQueue();
}
}, 50);

setTimeout(() => {
clearInterval(interval);
if (!loader.loaded) {
loader.loading = false;
algonomyLog("error", "SDK load timeout (10s)");
}
}, 10000);
}

function setCustomerIfExists() {
if (loader.customerSet) return;

const customer = init?.data?.customer;
if (customer?.id) {
const customerId = String(customer.id).split("/").pop();

try {
rcdp.setCustomer({
email: customer.email ?? "",
customerCode: customerId
});
loader.customerSet = true;
algonomyLog("log", "Customer identity set", customerId);
} catch (e) {
algonomyLog("error", "setCustomer failed", e);
}
}
}

function flushQueue() {
loader.queue.splice(0).forEach(fn => {
try { fn(); } catch (e) { algonomyLog("error", "Callback error", e); }
});
}
}
			

Payload Helpers

function encodePayload(payload) {
return btoa(unescape(encodeURIComponent(JSON.stringify(payload))));
}

function decodePayload(encoded) {
return JSON.parse(decodeURIComponent(escape(atob(encoded))));
}

function storePayload(payload) {
localStorage.setItem("__ALGONOMY_PAYLOAD", encodePayload(payload));
}

function getStoredPayload() {
const encoded = localStorage.getItem("__ALGONOMY_PAYLOAD");
return encoded ? decodePayload(encoded) : null;
}

function cacheBasePayload() {
if (!window.rcdp?.getEventPayload) return;
try {
const eventObj = rcdp.getEventPayload({}, "");
if (eventObj?.payload) storePayload(eventObj.payload);
} catch (e) {
algonomyLog("error", "Payload caching failed", e);
}
}
			

Homepage Detection Helper

function isHomepage(event) {
const pathname = event.context?.document?.location?.pathname || "";
const pageType = event.context?.page?.pageType || "";

return (
pathname === "/" ||
/^\/[a-z]{2}\/?$/.test(pathname) ||
pageType === "home" ||
pageType === "index"
);
}
			

Examples: Pixel rCDP Clickstream Integrations

The following examples cover standard eCommerce clickstream events implemented within Shopify Pixel.

Example 1: Home Page View

analytics.subscribe("page_viewed", (event) => {
if (!isHomepage(event)) return;

loadAlgonomy(() => {
rcdp.executeEventByData({}, "eventHomePage");
});
});
			

Example 2: Product View

analytics.subscribe("product_viewed", (event) => {
const variant = event.data?.productVariant;
if (!variant) return;

const data = {
productId: String(variant.product?.id ?? "").split("/").pop(),
price: String(variant.price?.amount ?? "0"),
brandId: variant.product?.vendor ?? "",
sku: variant.sku ?? "",
categoryId: ""
};

loadAlgonomy(() => {
AlgonomyPerf.measureEvent("eventProduct", () => {
rcdp.executeEventByData(data, "eventProduct");
});
});
});
			

Example 3: Add to Cart

analytics.subscribe("product_added_to_cart", (event) => {
const line = event.data?.cartLine;

if (!line) {
algonomyLog("warn", "cartLine missing", event.data);
return;
}

const eventData = {
productId: String(line.merchandise?.product?.id ?? "").split("/").pop(),
sku: line.merchandise?.sku ?? "",
price: String(line.merchandise?.price?.amount ?? "0"),
quantity: String(line.quantity ?? 1),
totalQuantity: String(line.quantity ?? 1)
};

loadAlgonomy(() => {
AlgonomyPerf.measureEvent("eventAddToCart", () => {
rcdp.executeEventByData(eventData, "eventAddToCart");
});
});
});
			

Example 4: Remove from Cart

analytics.subscribe("product_removed_from_cart", (event) => {
const line = event.data?.cartLine;

if (!line) {
algonomyLog("warn", "cartLine missing", event.data);
return;
}

const eventData = {
productId: String(line.merchandise?.product?.id ?? "").split("/").pop(),
sku: line.merchandise?.sku ?? "",
price: String(line.merchandise?.price?.amount ?? "0"),
quantity: String(line.quantity ?? 1)
};

loadAlgonomy(() => {
AlgonomyPerf.measureEvent("eventRemoveFromCart", () => {
rcdp.executeEventByData(eventData, "eventRemoveFromCart");
});
});
});
			

Example 5: Cart View

analytics.subscribe("cart_viewed", (event) => {
const lines = event.data?.cart?.lines || [];

const products = lines.map(line => ({
productId: String(line.merchandise?.product?.id ?? "").split("/").pop(),
sku: line.merchandise?.sku ?? "",
price: String(line.merchandise?.price?.amount ?? "0"),
quantity: String(line.quantity ?? 1)
}));

const eventData = {
products: products
};

loadAlgonomy(() => {
AlgonomyPerf.measureEvent("eventCartView", () => {
rcdp.executeEventByData(eventData, "eventCartView");
});
});
});
			

Example 6: Checkout Started

analytics.subscribe("checkout_started", (event) => {
const checkout = event.data?.checkout;

if (!checkout) return;

const eventData = {
checkoutId: checkout.id ?? "",
totalPrice: String(checkout.totalPrice?.amount ?? "0")
};

loadAlgonomy(() => {
AlgonomyPerf.measureEvent("eventCheckoutStart", () => {
rcdp.executeEventByData(eventData, "eventCheckoutStart");
});
});
});
			

Example 7: Checkout Completed (Order API)

Shopify Pixel does not expose complete order data directly. To capture full order details, you must call the Shopify Order API and then send the payload to rCDP.

analytics.subscribe("checkout_completed", async (event) => {
const checkoutId = event.data?.checkout?.id;

if (!checkoutId) return;

try {
const response = await fetch(`/orders/${checkoutId}.json`);
const order = await response.json();

const eventData = {
orderId: order.id,
totalPrice: order.total_price,
currency: order.currency
};

loadAlgonomy(() => {
AlgonomyPerf.measureEvent("eventPurchase", () => {
rcdp.executeEventByData(eventData, "eventPurchase");
});
});

} catch (e) {
algonomyLog("error", "Order fetch failed", e);
}
});
			

Note: Access to order data may require additional permissions depending on Shopify configuration.

Sandbox Constraints

Shopify Web Pixels run inside a sandboxed iframe environment. This introduces certain limitations that must be considered during implementation.

  • Limited access to global window variables

  • Restricted DOM manipulation capabilities

  • External script loading must follow Shopify policies

  • Strict execution boundaries for security

Note: Always validate that your implementation complies with Shopify’s Web Pixel restrictions.

Key Considerations

  • Ensure SDK is loaded before firing events

  • Avoid duplicate event firing

  • Validate payload structure against event taxonomy

  • Handle missing or null data gracefully

  • Test all events in Shopify preview mode

Tip: Combine Pixel Instrumentation with No-Code tracking for a hybrid approach that balances speed and flexibility.

Summary

Shopify Pixel Instrumentation provides a flexible and powerful way to implement clickstream tracking with full control over event data. While it requires development effort, it enables advanced customization and supports complex tracking scenarios.

For most standard use cases, No-Code Instrumentation is recommended. Pixel Instrumentation should be used when additional flexibility and customization are required.

Next Steps

  • Review Shopify No-Code Instrumentation

  • Validate events using rCDP dashboard

  • Proceed to Clickstream Event APIs