Connect Shopify with JDTechSpace Analytics
Track storefront visitors, sessions, page activity and ecommerce behaviour from Shopify in one analytics system.
1. Get your Site ID
Every website connected to JDTechSpace Analytics has a unique Site ID. This ID connects Shopify activity to the correct analytics property.
Open your Analytics website
Open your JDTechSpace Analytics dashboard and select the Shopify website you want to connect.
2. Install storefront tracking
The normal JDTechSpace Analytics script should be installed in your Shopify theme. This handles storefront analytics such as visitors, sessions, UTM parameters, engagement, clicks and scroll activity.
Open your Shopify theme
From Shopify Admin, open your theme code and locate the main theme layout.
<script
src="https://jdtechspace.com/assets/js/analytics.js"
data-site-id="YOUR_SITE_ID">
</script>
Use the Site ID assigned to this Shopify website in JDTechSpace Analytics.
3. Configure Shopify Custom Pixel
Shopify's Web Pixels API provides the Customer Events system used to subscribe to standard events across the storefront, checkout and order-status experience. :contentReference[oaicite:1]{index=1}
Shopify Custom Pixels accept JavaScript directly. Do not paste the normal HTML <script src="..."> installation here. The Custom Pixel uses Shopify's analytics.subscribe() API instead. :contentReference[oaicite:2]{index=2}
Open Customer Events
In Shopify Admin, open the Customer Events section and create a new Custom Pixel.
Create a Custom Pixel
Create a custom pixel and give it a name such as:
4. Paste the Custom Pixel code
Paste the following JavaScript directly into Shopify's Custom Pixel editor. The code subscribes to Shopify's standard customer events and forwards them to JDTechSpace Analytics. Shopify Custom Pixels already provide analytics, browser and init APIs without the normal app-pixel registration wrapper. :contentReference[oaicite:3]{index=3}
The rest of the code can be used as provided. Keep the Site ID exactly as assigned in JDTechSpace Analytics.
/*
|--------------------------------------------------------------------------
| JDTechSpace Analytics — Shopify Custom Pixel
|--------------------------------------------------------------------------
|
| Paste this code directly into:
|
| Shopify Admin
| → Settings
| → Customer events
| → Add custom pixel
|
| IMPORTANT:
| This code is for Shopify Customer Events only.
| Do NOT add script tags.
|*/
(function () {
"use strict";
/*
|--------------------------------------------------------------------------
| CONFIGURATION
|--------------------------------------------------------------------------
*/
const SITE_ID = "SITE_ID";
const COLLECT_URL = "https://jdtechspace.com/api/analytics/collect.php";
/*
|--------------------------------------------------------------------------
| STORAGE
|--------------------------------------------------------------------------
|
| Shopify Custom Pixels have a different execution environment
| from the normal storefront theme.
|
| We maintain our own visitor/session identifiers here.
|
*/
function getStorage(key) {
try {
return localStorage.getItem(key);
} catch (error) {
return null;
}
}
function setStorage(key, value) {
try {
localStorage.setItem(key, value);
} catch (error) {
// Ignore storage errors
}
}
/*
|--------------------------------------------------------------------------
| GENERATE ID
|--------------------------------------------------------------------------
*/
function generateId(prefix) {
return (
prefix +
"_" +
Date.now().toString(36) +
"_" +
Math.random().toString(36).substring(2, 12)
);
}
/*
|--------------------------------------------------------------------------
| VISITOR ID
|--------------------------------------------------------------------------
*/
let visitorId = getStorage("jd_analytics_visitor");
if (!visitorId) {
visitorId = generateId("v");
setStorage("jd_analytics_visitor", visitorId);
}
/*
|--------------------------------------------------------------------------
| SESSION ID
|--------------------------------------------------------------------------
*/
const SESSION_TIMEOUT = 30 * 60 * 1000;
let sessionId = getStorage("jd_analytics_session");
let sessionStarted = getStorage("jd_analytics_session_started");
const now = Date.now();
if (
!sessionId ||
!sessionStarted ||
now - parseInt(sessionStarted, 10) > SESSION_TIMEOUT
) {
sessionId = generateId("s");
sessionStarted = now.toString();
setStorage("jd_analytics_session", sessionId);
setStorage("jd_analytics_session_started", sessionStarted);
}
/*
|--------------------------------------------------------------------------
| PAGE INFORMATION
|--------------------------------------------------------------------------
|
| Shopify Customer Events does not use the normal storefront
| document context in the same way as theme JavaScript.
|
| We therefore safely read available Shopify event context.
|
*/
function getPageUrl(event) {
try {
if (
event &&
event.context &&
event.context.document &&
event.context.document.location &&
event.context.document.location.href
) {
return event.context.document.location.href;
}
} catch (error) {
// Ignore
}
try {
if (
typeof window !== "undefined" &&
window.location &&
window.location.href
) {
return window.location.href;
}
} catch (error) {
// Ignore
}
return "";
}
function getPageTitle(event) {
try {
if (
event &&
event.context &&
event.context.document &&
event.context.document.title
) {
return event.context.document.title;
}
} catch (error) {
// Ignore
}
try {
if (typeof document !== "undefined" && document.title) {
return document.title;
}
} catch (error) {
// Ignore
}
return "";
}
function getReferrer(event) {
try {
if (
event &&
event.context &&
event.context.document &&
event.context.document.referrer
) {
return event.context.document.referrer;
}
} catch (error) {
// Ignore
}
try {
if (typeof document !== "undefined" && document.referrer) {
return document.referrer;
}
} catch (error) {
// Ignore
}
return null;
}
/*
|--------------------------------------------------------------------------
| UTM PARAMETERS
|--------------------------------------------------------------------------
*/
function getUTM(url) {
const result = {
source: null,
medium: null,
campaign: null,
term: null,
content: null,
};
if (!url) {
return result;
}
try {
const parsed = new URL(url);
result.source = parsed.searchParams.get("utm_source");
result.medium = parsed.searchParams.get("utm_medium");
result.campaign = parsed.searchParams.get("utm_campaign");
result.term = parsed.searchParams.get("utm_term");
result.content = parsed.searchParams.get("utm_content");
} catch (error) {
// Ignore invalid URL
}
return result;
}
/*
|--------------------------------------------------------------------------
| NORMALIZE NUMBER
|--------------------------------------------------------------------------
*/
function number(value) {
if (value === null || value === undefined || value === "") {
return undefined;
}
const parsed = Number(value);
return Number.isFinite(parsed) ? parsed : undefined;
}
/*
|--------------------------------------------------------------------------
| SEND EVENT
|--------------------------------------------------------------------------
*/
function sendEvent(eventName, eventData, sourceEvent) {
if (!eventName) {
return;
}
const pageUrl = getPageUrl(sourceEvent);
const pageTitle = getPageTitle(sourceEvent);
const utm = getUTM(pageUrl);
const payload = {
site_id: SITE_ID,
visitor_id: visitorId,
session_id: sessionId,
event_name: eventName,
page_url: pageUrl,
page_title: pageTitle,
referrer: getReferrer(sourceEvent),
utm_source: utm.source,
utm_medium: utm.medium,
utm_campaign: utm.campaign,
utm_term: utm.term,
utm_content: utm.content,
screen_width:
typeof window !== "undefined" && window.screen ? window.screen.width
: 0,
screen_height:
typeof window !== "undefined" && window.screen ? window.screen.height
: 0,
language:
typeof navigator !== "undefined" ? navigator.language || null : null,
device_type: getDeviceType(),
browser: getBrowser(),
os: getOS(),
event_data: eventData || {},
};
try {
fetch(COLLECT_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
}).catch(function () {
// Never interfere with Shopify
});
} catch (error) {
// Never interfere with Shopify
}
}
/*
|--------------------------------------------------------------------------
| DEVICE
|--------------------------------------------------------------------------
*/
function getDeviceType() {
try {
const width = window.innerWidth;
if (width <= 767) {
return "mobile";
}
if (width <= 1024) {
return "tablet";
}
return "desktop";
} catch (error) {
return "unknown";
}
}
/*
|--------------------------------------------------------------------------
| BROWSER
|--------------------------------------------------------------------------
*/
function getBrowser() {
try {
const ua = navigator.userAgent || "";
if (ua.includes("Edg/")) {
return "Edge";
}
if (ua.includes("OPR/")) {
return "Opera";
}
if (ua.includes("Chrome/")) {
return "Chrome";
}
if (ua.includes("Firefox/")) {
return "Firefox";
}
if (ua.includes("Safari/") && !ua.includes("Chrome/")) {
return "Safari";
}
} catch (error) {
// Ignore
}
return "Unknown";
}
/*
|--------------------------------------------------------------------------
| OPERATING SYSTEM
|--------------------------------------------------------------------------
*/
function getOS() {
try {
const ua = navigator.userAgent || "";
if (/Windows/i.test(ua)) {
return "Windows";
}
if (/Android/i.test(ua)) {
return "Android";
}
if (/iPhone|iPad|iPod/i.test(ua)) {
return "iOS";
}
if (/Mac OS X/i.test(ua)) {
return "macOS";
}
if (/Linux/i.test(ua)) {
return "Linux";
}
} catch (error) {
// Ignore
}
return "Unknown";
}
/*
|--------------------------------------------------------------------------
| ITEM FORMATTER
|--------------------------------------------------------------------------
*/
function formatItem(item) {
if (!item) {
return {};
}
const formatted = {};
/*
|----------------------------------------------------------------------
| Product ID
|----------------------------------------------------------------------
*/
if (item.product && item.product.id !== undefined) {
formatted.product_id = String(item.product.id);
}
/*
|----------------------------------------------------------------------
| Product Title
|----------------------------------------------------------------------
*/
if (item.product && item.product.title) {
formatted.product_name = item.product.title;
}
/*
|----------------------------------------------------------------------
| Variant ID
|----------------------------------------------------------------------
*/
if (item.variant && item.variant.id !== undefined) {
formatted.variant_id = String(item.variant.id);
}
/*
|----------------------------------------------------------------------
| Variant Title
|----------------------------------------------------------------------
*/
if (item.variant && item.variant.title) {
formatted.variant_name = item.variant.title;
}
/*
|----------------------------------------------------------------------
| Quantity
|----------------------------------------------------------------------
*/
if (item.quantity !== undefined) {
formatted.quantity = number(item.quantity);
}
/*
|----------------------------------------------------------------------
| Price
|----------------------------------------------------------------------
*/
if (item.price !== undefined) {
formatted.price = number(item.price);
}
return formatted;
}
/*
|--------------------------------------------------------------------------
| ADD TO CART
|--------------------------------------------------------------------------
*/
analytics.subscribe("product_added_to_cart", function (event) {
const data = event.data || {};
const cartLine = data.cartLine || {};
const merchandise = cartLine.merchandise || {};
const quantity = number(cartLine.quantity);
const price = number(merchandise.price);
const itemValue =
price !== undefined && quantity !== undefined ? price * quantity
: undefined;
const eventData = {};
if (merchandise.product && merchandise.product.id !== undefined) {
eventData.product_id = String(merchandise.product.id);
}
if (merchandise.product && merchandise.product.title) {
eventData.product_name = merchandise.product.title;
}
if (merchandise.id !== undefined) {
eventData.variant_id = String(merchandise.id);
}
if (merchandise.title) {
eventData.variant_name = merchandise.title;
}
if (quantity !== undefined) {
eventData.quantity = quantity;
}
if (price !== undefined) {
eventData.price = price;
}
if (itemValue !== undefined) {
eventData.value = itemValue;
}
if (merchandise.price && merchandise.price.currencyCode) {
eventData.currency = merchandise.price.currencyCode;
}
sendEvent("add_to_cart", eventData, event);
});
/*
|--------------------------------------------------------------------------
| BEGIN CHECKOUT
|--------------------------------------------------------------------------
*/
analytics.subscribe("checkout_started", function (event) {
const checkout =
event.data && event.data.checkout ? event.data.checkout : {};
const eventData = {};
/*
|----------------------------------------------------------------------
| Checkout Value
|----------------------------------------------------------------------
*/
if (checkout.totalPrice && checkout.totalPrice.amount !== undefined) {
eventData.value = number(checkout.totalPrice.amount);
}
/*
|----------------------------------------------------------------------
| Currency
|----------------------------------------------------------------------
*/
if (checkout.currencyCode) {
eventData.currency = checkout.currencyCode;
}
/*
|----------------------------------------------------------------------
| Checkout Items
|----------------------------------------------------------------------
*/
if (checkout.lineItems && Array.isArray(checkout.lineItems)) {
eventData.items = checkout.lineItems.map(function (item) {
return formatItem(item);
});
}
sendEvent("begin_checkout", eventData, event);
});
/*
|--------------------------------------------------------------------------
| PURCHASE
|--------------------------------------------------------------------------
*/
analytics.subscribe("checkout_completed", function (event) {
const checkout =
event.data && event.data.checkout ? event.data.checkout : {};
const eventData = {};
/*
|----------------------------------------------------------------------
| Order ID
|----------------------------------------------------------------------
*/
if (checkout.order && checkout.order.id !== undefined) {
eventData.order_id = String(checkout.order.id);
}
/*
|----------------------------------------------------------------------
| Checkout ID
|----------------------------------------------------------------------
*/
if (checkout.id !== undefined) {
eventData.checkout_id = String(checkout.id);
}
/*
|----------------------------------------------------------------------
| Purchase Value
|----------------------------------------------------------------------
*/
if (checkout.totalPrice && checkout.totalPrice.amount !== undefined) {
eventData.value = number(checkout.totalPrice.amount);
}
/*
|----------------------------------------------------------------------
| Currency
|----------------------------------------------------------------------
*/
if (checkout.currencyCode) {
eventData.currency = checkout.currencyCode;
}
/*
|----------------------------------------------------------------------
| Items
|----------------------------------------------------------------------
*/
if (checkout.lineItems && Array.isArray(checkout.lineItems)) {
eventData.items = checkout.lineItems.map(function (item) {
return formatItem(item);
});
}
sendEvent("purchase", eventData, event);
});
})();
Save the Custom Pixel and connect it to the Shopify store. Shopify's Web Pixels API will then provide the subscribed standard events to the pixel. :contentReference[oaicite:4]{index=4}
5. Ecommerce events
Shopify's standard customer events are mapped into the JDTechSpace Analytics event model.
| Shopify Event | JDTechSpace Event | Purpose |
|---|---|---|
| page_viewed | page_view | Page visit |
| product_added_to_cart | add_to_cart | Product added to cart |
| checkout_started | begin_checkout | Checkout started |
| checkout_completed | purchase | Purchase completed |
add_to_cart
AutomaticJDTechSpace receives the product and cart-line information supplied by Shopify's product_added_to_cart event. :contentReference[oaicite:5]{index=5}
begin_checkout
AutomaticShopify's checkout_started event is mapped to begin_checkout. :contentReference[oaicite:6]{index=6}
purchase
AutomaticShopify's checkout_completed event is mapped to purchase. :contentReference[oaicite:7]{index=7}
6. Verify tracking
After saving and connecting the Custom Pixel, open your Shopify storefront and perform a normal customer journey.
Shopify exposes page metadata through the event context, including event.context.document.location.href and event.context.document.title. :contentReference[oaicite:8]{index=8}
7. Test the complete journey
Test the complete customer journey before considering the integration ready for production traffic.
Test your Shopify store
A successful page view does not necessarily confirm ecommerce tracking. Test the complete add-to-cart → checkout → purchase journey.