Shopify Analytics Setup | JDTechSpace Analytics
SHOPIFY INTEGRATION

Connect Shopify with JDTechSpace Analytics

Track storefront visitors, sessions, page activity and ecommerce behaviour from Shopify in one analytics system.

Before you begin
Shopify store
JDTechSpace Analytics account
Website added to Analytics
Shopify Admin access

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.

01

Open your Analytics website

Open your JDTechSpace Analytics dashboard and select the Shopify website you want to connect.

Analytics Websites Your Shopify Store

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.

02

Open your Shopify theme

From Shopify Admin, open your theme code and locate the main theme layout.

Shopify Admin Online Store Themes Edit code
Add the Analytics script HTML
<script
    src="https://jdtechspace.com/assets/js/analytics.js"
    data-site-id="YOUR_SITE_ID">
</script>
Replace YOUR_SITE_ID

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}

Do not paste analytics.js here

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}

03

Open Customer Events

In Shopify Admin, open the Customer Events section and create a new Custom Pixel.

Shopify Admin Settings Customer events
04

Create a Custom Pixel

Create a custom pixel and give it a name such as:

JDTechSpace Analytics

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}

Replace only YOUR_SITE_ID

The rest of the code can be used as provided. Keep the Site ID exactly as assigned in JDTechSpace Analytics.

JDTechSpace Shopify Custom Pixel JavaScript
/*
|--------------------------------------------------------------------------
| 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);
  });
})();
That's it.

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

Automatic

JDTechSpace receives the product and cart-line information supplied by Shopify's product_added_to_cart event. :contentReference[oaicite:5]{index=5}

Product ID
Product name
Variant ID
Variant name
Quantity
Value / Currency

begin_checkout

Automatic

Shopify's checkout_started event is mapped to begin_checkout. :contentReference[oaicite:6]{index=6}

Checkout value
Currency
Product items
Quantity

purchase

Automatic

Shopify's checkout_completed event is mapped to purchase. :contentReference[oaicite:7]{index=7}

Order ID
Purchase value
Currency
Purchased items

6. Verify tracking

After saving and connecting the Custom Pixel, open your Shopify storefront and perform a normal customer journey.

Page view appears
Visitor is recorded
Session is created
Page URL appears
Page title appears
Ecommerce events appear
Page URL and page title

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.

07

Test your Shopify store

Open the store
Open a product
Add product to cart
Start checkout
Complete test purchase
Verify Analytics dashboard
Do not test only with page views

A successful page view does not necessarily confirm ecommerce tracking. Test the complete add-to-cart → checkout → purchase journey.