Install MetricMind on ShopifyBeta

Paste the script tag into your theme's theme.liquid for the store's pages, then add MetricMind's custom pixel under Settings → Customer events for checkout and sales.

Shopify support is in beta. We checked the pixel's field names against Shopify's docs, but it hasn't been run on a real store yet. Check your first events and sales against Shopify's own numbers.

Add the tag

Replace YOUR_SITE_ID with your site's ID. In MetricMind, open your site, then Settings → Setup. The ID is in the header of the Install it yourself panel, and the Script tag tab there shows the tag with your ID already filled in.

Part 1: the tag in your theme

This measures your store's pages. Shopify recommends duplicating your theme first, so you have a copy to go back to. If you're trying a paid theme, you have to buy it before you can edit its code.

  1. In your Shopify admin, go to Online Store.
  2. Click the … menu next to your theme, then Edit code.
  3. Open layout/theme.liquid.
  4. Paste the tag on the line just before </head>, then click Save.
    <script src="https://cdn.metricmind.si/mm.js" data-site="YOUR_SITE_ID" defer></script>

Part 2: the pixel for checkout and sales

This sends add to cart, begin checkout, payment info and purchase with its value.

  1. Go to Settings → Customer events, and add a custom pixel.
  2. Give it a name, such as MetricMind, then click Add pixel.
  3. Under Customer privacy, set Permission. See the note on consent below.
  4. Paste this into the Code window. Replace YOUR_SITE_ID on its second line.
    // MetricMind: checkout events and sales. Keep the mm.js script in your theme for the store's pages.
    const SITE = "YOUR_SITE_ID";
    const API = "https://in.metricmind.si/v1/batch";
    const IDLE = 30 * 60 * 1000;
    
    const uuid = () => crypto.randomUUID ? crypto.randomUUID() : "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
    const get = (key) => browser.localStorage.getItem(key).catch(() => null);
    const set = (key, value) => browser.localStorage.setItem(key, value).catch(() => {});
    
    async function ids() {
      const now = Date.now();
      const visitor = (await get("mm_vid")) || uuid();
      const seen = Number(await get("mm_seen")) || 0;
      const session = (now - seen < IDLE && (await get("mm_sid"))) || uuid();
      await Promise.all([set("mm_vid", visitor), set("mm_sid", session), set("mm_seen", String(now))]);
      return { visitor, session };
    }
    
    async function send(event, name, props, revenue) {
      if (await get("mm_optout")) return;
      const page = event.context && event.context.document && event.context.document.location;
      const path = page && page.pathname;
      fetch(API, {
        method: "POST",
        keepalive: true,
        headers: { "Content-Type": "text/plain" },
        body: JSON.stringify({
          site: SITE,
          source: "shopify",
          events: [{
            id: uuid(),
            type: "event",
            ts: Date.now(),
            ...(await ids()),
            // Checkout addresses carry tokens: every checkout page is one path.
            path: !path || path.includes("/checkouts") ? "/checkouts/*" : path,
            name,
            props,
            revenue,
          }],
        }),
      }).catch(() => {});
    }
    
    const total = (checkout) => checkout.totalPrice && Number(checkout.totalPrice.amount);
    
    analytics.subscribe("product_added_to_cart", (event) => {
      const line = event.data.cartLine;
      if (!line) return;
      send(event, "add_to_cart", { product: line.merchandise.product.title, quantity: line.quantity, value: Number(line.cost.totalAmount.amount), currency: line.cost.totalAmount.currencyCode });
    });
    analytics.subscribe("checkout_started", (event) => {
      send(event, "begin_checkout", { value: total(event.data.checkout), currency: event.data.checkout.currencyCode });
    });
    analytics.subscribe("payment_info_submitted", (event) => {
      send(event, "add_payment_info", { value: total(event.data.checkout), currency: event.data.checkout.currencyCode });
    });
    analytics.subscribe("checkout_completed", (event) => {
      const checkout = event.data.checkout;
      const order = (checkout.order && checkout.order.id) || checkout.token;
      send(event, "purchase", { items: checkout.lineItems ? checkout.lineItems.length : 0 }, { amount: total(checkout), currency: checkout.currencyCode, order_id: order ? String(order) : undefined });
    });
  5. Click Save, then Connect pixel.

Check that it works

  1. Open your live site in a normal browser window, with ad blockers off, and load a page or two.
  2. In MetricMind, open your site's Settings → Setup page. The panel at the top says Waiting until the first page view arrives, then Live. It usually takes under a minute. Reload the page if it hasn't changed.
  3. To check the pixel, go to Settings → Customer events, click your pixel, then Test. Shopify opens your store with a Pixel helper: add something to the cart and watch Events received. If it says Pixel is awaiting consent, accept your banner or click Give consent to continue test.

Still on Waiting?

  • An ad blocker in your browser. Some block analytics. Test with extensions off.
  • A different address. Events are accepted from the domain you registered in MetricMind, its www. version and its subdomains. To test on another address, such as your platform's free or staging domain, add it under Settings → Security → Allowed origins.
  • Local testing. The script ignores localhost and private addresses, so test on the live site.
  • The tag didn't arrive. View your page's source and search for mm.js. If it's there, open your browser's developer tools: [MetricMind] Missing data-site in the Console means the tag lost its ID, and in the Network tab /v1/batch should answer 202.

What goes wrong on Shopify

The checkout doesn't run your theme's scripts

A script in your theme stops at the checkout. Shopify has also retired checkout.liquid and additional scripts on the Thank you and Order status pages, so those aren't a way around it. Custom pixels are what can collect events on checkout and post-purchase pages, which is why you need both parts.

Consent decides what the pixel sees

If Permission is Required for analytics, then where Shopify asks for consent the pixel runs only for shoppers who accept, so sales there are undercounted. Not required counts them all, and that choice is yours to make with your counsel. Totals are as reported by the browser, so they can differ from Shopify's own.

Shopify says to remove theme code first. Keep this one.

Shopify's pixel steps ask you to remove pixel code from theme.liquid so events don't count twice. The two MetricMind parts send different things: the tag measures pages and the pixel sends the cart and checkout events, so keep both.

Theme changes can drop the tag

If your edit doesn't fit a theme update, Shopify removes it from the updated copy, and a different theme doesn't have it at all. If page views stop after a theme change, paste the tag again.

Privacy

MetricMind sets no cookies and builds no profiles. In the EU, storing an ID on the device can need consent even without cookies, so for the strictest reading turn on storage-free mode (data-storage="none"), which stores nothing in the browser. Your obligations depend on your jurisdiction and the rest of your stack, so check with your counsel.

You can add data-storage="none" to the tag in your theme, but the pixel always keeps a visitor ID and session ID in the browser's storage, so a store using the pixel doesn't get a storage-free setup. What changes in that mode.

Next

  • To leave out your own visits, open https://yoursite.com/?mm_optout=1 once in each browser you use (=0 turns it back on).
  • Page views, sources, contact clicks, site search, Web Vitals and errors are collected without more setup. To count your own actions, see events.

Sources

The steps and plan rules come from these pages, as of November 2026. Platforms change their menus, so tell us if something has moved.