Approach 1: Native Installation

ClickMint CRO Platform — Client Documentation

Who this is for: Developers with direct access to the site's HTML, theme files, or application code. No tag manager required.


Overview

In this approach, both the GA4 tracking snippet and the ClickMint script are added directly to your site's source code — the same place you'd add any <script> tag. There is no tag manager involved.

This is the most straightforward setup. It gives ClickMint direct, guaranteed access to gtag() and window.dataLayer with no intermediary layers.


Prerequisites

Before starting, have the following ready:

  • GA4 Measurement ID — found in GA4 → Admin → Data Streams → Web → Measurement ID. Format: G-XXXXXXXXXX.
  • ClickMint Org ID — found in your ClickMint dashboard → Settings → Organization. Format: org_XXXXXXXXXX. The script URL uses only the part after org_ (e.g., org_abc123abc123).
  • Code editor access to your site's template or layout file.

Load Order — Why It Matters

The ClickMint script calls gtag() when it runs. If GA4 hasn't loaded yet, it will retry for up to 3 seconds. To avoid any delay in experiment assignment, always load scripts in this order:

  1. GA4 snippet (gtag.js) — loads and initializes window.gtag() and window.dataLayer
  2. ClickMint script — loads and fires experiment logic against gtag()

Both scripts should be in the <head> of your HTML, not at the bottom of <body>.


The Two Snippets

Snippet 1 — GA4

Replace G-XXXXXXXXXX with your Measurement ID:

<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || []
  function gtag() {
    dataLayer.push(arguments)
  }
  gtag('js', new Date())
  gtag('config', 'G-XXXXXXXXXX')
</script>

Snippet 2 — ClickMint

Replace YOUR_ORG_ID with the identifier portion of your org ID (the part after org_):

<!-- ClickMint experiment script -->
<script>
  ;(function () {
    var currentPath = location.pathname
    var previewStorageKey = 'cm_preview_' + currentPath
    var referrerStorageKey = 'cm_referrer_' + currentPath
    var params = new URLSearchParams(location.search)
    var previewParam = params.get('cm_preview')
    var referrerParam = params.get('cm_referrer')

    if (previewParam) {
      localStorage.setItem(previewStorageKey, previewParam)
    }
    if (referrerParam) {
      localStorage.setItem(referrerStorageKey, referrerParam)
    }

    var baseUrl = 'https://experiments.api.clickmint.com/YOUR_ORG_ID' + currentPath
    var queryParts = []

    var storedPreview = localStorage.getItem(previewStorageKey)
    if (storedPreview) {
      queryParts.push('cm_preview=' + encodeURIComponent(storedPreview))
    }

    var storedReferrer = localStorage.getItem(referrerStorageKey)
    if (storedReferrer) {
      queryParts.push('cm_referrer=' + encodeURIComponent(storedReferrer))
    }

    var scriptUrl = baseUrl + (queryParts.length > 0 ? '?' + queryParts.join('&') : '')
    var script = document.createElement('script')
    script.async = true
    script.src = scriptUrl
    ;(document.head || document.documentElement).appendChild(script)
  })()
</script>

💡 How the URL works: The script fetches https://experiments.api.clickmint.com/{orgId}{page-path}. Each page loads its own experiment configuration — ClickMint only activates on pages where you have an active experiment.


Platform-Specific Instructions

Shopify

File to edit: layout/theme.liquid (Shopify Online Store 2.0) or layout/theme.liquid / snippets/ (Classic themes).

  1. Go to Shopify Admin → Online Store → Themes.
  2. Click the ... next to your active theme → Edit code.
  3. Open layout/theme.liquid.
  4. Find the closing </head> tag.
  5. Paste the GA4 snippet before </head>, then paste the ClickMint snippet immediately after it (still before </head>):
  <!-- Google tag (gtag.js) -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
  <script>
    window.dataLayer = window.dataLayer || []
    function gtag() { dataLayer.push(arguments) }
    gtag('js', new Date())
    gtag('config', 'G-XXXXXXXXXX')
  </script>

  <!-- ClickMint experiment script -->
  <script>
    (function () {
      /* ...ClickMint snippet... */
    })()
  </script>
</head>
  1. Remove any existing GA4 integration from Shopify's built-in settings:
    • Go to Settings → Apps and sales channels → Google & YouTube → remove the GA4 property connection, OR
    • Go to Online Store → Preferences → clear the Google Analytics Measurement ID field.
  2. Do not use Shopify Pixels (Customer Events) for the GA4 base tag — Shopify Pixels run in a sandboxed iframe that blocks dataLayer access.
  3. Save and preview on a storefront page.

⚠️ Checkout pages (Shopify Plus): Edit checkout.liquid to add the same two snippets. Non-Plus merchants: the standard theme snippet covers all non-checkout pages. Use Shopify's server-side Web Pixels for checkout event tracking if needed.


Next.js / React (App Router)

File to edit: app/layout.tsx (or .jsx)

Use Next.js's <Script> component with strategy="beforeInteractive" so both scripts load before the page hydrates:

import Script from 'next/script'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        {/* GA4 */}
        <Script src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX" strategy="beforeInteractive" />
        <Script id="ga4-init" strategy="beforeInteractive">
          {`
            window.dataLayer = window.dataLayer || [];
            function gtag(){ dataLayer.push(arguments); }
            gtag('js', new Date());
            gtag('config', 'G-XXXXXXXXXX');
          `}
        </Script>

        {/* ClickMint */}
        <Script id="clickmint-script" strategy="beforeInteractive">
          {`
            (function(){
              var currentPath = location.pathname;
              /* ...rest of ClickMint snippet... */
            })();
          `}
        </Script>
      </head>
      <body>{children}</body>
    </html>
  )
}

💡 beforeInteractive vs afterInteractive: Use beforeInteractive to guarantee the scripts load before any React components mount — this prevents a race condition where a user navigates before the experiment script fires.


Next.js / React (Pages Router)

File to edit: pages/_app.tsx (or .jsx)

import { useEffect } from 'react'
import Script from 'next/script'
import type { AppProps } from 'next/app'

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <Script src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX" strategy="beforeInteractive" />
      <Script id="ga4-init" strategy="beforeInteractive">
        {`
          window.dataLayer = window.dataLayer || [];
          function gtag(){ dataLayer.push(arguments); }
          gtag('js', new Date());
          gtag('config', 'G-XXXXXXXXXX');
        `}
      </Script>
      <Script id="clickmint-script" strategy="beforeInteractive">
        {`
          (function(){
            var currentPath = location.pathname;
            /* ...rest of ClickMint snippet... */
          })();
        `}
      </Script>
      <Component {...pageProps} />
    </>
  )
}

WordPress

Option A — via functions.php (theme):

Add to your active theme's functions.php:

function clickmint_head_scripts() {
  ?>
  <!-- Google tag (gtag.js) -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){ dataLayer.push(arguments); }
    gtag('js', new Date());
    gtag('config', 'G-XXXXXXXXXX');
  </script>

  <!-- ClickMint experiment script -->
  <script>
    (function(){
      var currentPath = location.pathname;
      /* ...rest of ClickMint snippet... */
    })();
  </script>
  <?php
}
add_action('wp_head', 'clickmint_head_scripts', 1);

The priority 1 ensures these scripts load before other wp_head hooks.

Option B — via a header/footer plugin (e.g., Insert Headers and Footers):

  1. Install and activate a plugin like Insert Headers and Footers or WPCode.
  2. Paste the GA4 snippet into the Header section.
  3. Paste the ClickMint snippet into the Header section immediately below GA4.
  4. Save and publish.

⚠️ Disable any existing GA4 plugin (e.g., Site Kit by Google, MonsterInsights) that may already be injecting GA4. Two conflicting GA4 installations will cause duplicate events.


Generic HTML

For any site where you can edit the <head> of your HTML template directly:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Your Site</title>

    <!-- Google tag (gtag.js) — FIRST -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
    <script>
      window.dataLayer = window.dataLayer || []
      function gtag() {
        dataLayer.push(arguments)
      }
      gtag('js', new Date())
      gtag('config', 'G-XXXXXXXXXX')
    </script>

    <!-- ClickMint experiment script — SECOND, after GA4 -->
    <script>
      ;(function () {
        var currentPath = location.pathname
        var previewStorageKey = 'cm_preview_' + currentPath
        var referrerStorageKey = 'cm_referrer_' + currentPath
        var params = new URLSearchParams(location.search)
        var previewParam = params.get('cm_preview')
        var referrerParam = params.get('cm_referrer')

        if (previewParam) {
          localStorage.setItem(previewStorageKey, previewParam)
        }
        if (referrerParam) {
          localStorage.setItem(referrerStorageKey, referrerParam)
        }

        var baseUrl = 'https://experiments.api.clickmint.com/YOUR_ORG_ID' + currentPath
        var queryParts = []

        var storedPreview = localStorage.getItem(previewStorageKey)
        if (storedPreview) {
          queryParts.push('cm_preview=' + encodeURIComponent(storedPreview))
        }

        var storedReferrer = localStorage.getItem(referrerStorageKey)
        if (storedReferrer) {
          queryParts.push('cm_referrer=' + encodeURIComponent(storedReferrer))
        }

        var scriptUrl = baseUrl + (queryParts.length > 0 ? '?' + queryParts.join('&') : '')
        var script = document.createElement('script')
        script.async = true
        script.src = scriptUrl
        ;(document.head || document.documentElement).appendChild(script)
      })()
    </script>
  </head>
  <body>
    <!-- page content -->
  </body>
</html>

Verifying Your Setup

Step 1 — Check the cm_tracking event in GA4 DebugView

  1. Navigate to a page where you have an active experiment.
  2. In GA4, go to Admin → DebugView.
  3. Look for a cm_tracking event. Click it to expand.
  4. Verify it has experiment_id, outcome_id, and event_type parameters.

Step 2 — Check for duplicate GA4 tags

In the browser console, run:

document.querySelectorAll('script[src*="googletagmanager.com/gtag/js"]').length

This should return 1. If it returns 2 or more, find and remove the duplicate.

Step 3 — Confirm user properties are set

In the browser console, look for the ClickMint log:

[ClickMint] User properties set for conversion tracking.

If you see this, the experiment assignment has been recorded against GA4.


Troubleshooting

SymptomLikely causeFix
cm_tracking event missing from DebugViewClickMint script not loadingCheck network tab for a request to experiments.api.clickmint.com — confirm 200 response
cm_tracking event appears but has no experiment_idNo active experiment on this URLCreate or activate an experiment for this page in the ClickMint dashboard
Experiment fires but conversions show as zeroGA4 custom dimensions not registeredRegister all CM custom dimensions (event-scoped and user-scoped) and the cm_tracking custom event in GA4 Admin → Custom Definitions — see the custom dimensions FAQ → wait 24–48h
Duplicate page_view events in GA4Two GA4 snippets on the pageRemove the old GA4 tag (plugin, theme setting, or inline snippet)
gtag is not defined in consoleGA4 snippet not loading before ClickMintCheck script order in the <head> — GA4 must be firs