Approach 3: GTM Serverless Configuration
ClickMint CRO Platform — Client Documentation
Who this is for: Agency partners and advanced GTM users with complex tag setups — server-side GTM (sGTM), Consent Mode v2, multi-destination GA4 configurations, or Elevar-managed containers — where replacing the existing Google Tag is not practical.
Overview
This approach adds ClickMint experiment tracking on top of your existing GA4 setup — without replacing or modifying your current Google Tag, GA4 Configuration tag, or any tags managed by Elevar, Consent Mode v2, or sGTM.
Instead of sending tracking events through the GA4 JavaScript library directly, ClickMint pushes data to the dataLayer. GTM intercepts the cm_tracking event via a Custom Event trigger, then routes it through a dedicated GA4 Event tag. Your existing GA4 infrastructure is completely untouched.
Result: ClickMint experiment data flows to GA4 cleanly and reliably, with no risk of breaking your existing tag setup.
When to Use This Approach
Use Approach 3 if any of the following apply:
- You use server-side GTM (sGTM) or a GTM configuration managed by a third party (Elevar, Littledata, etc.)
- You have Consent Mode v2 set up with a CMP (OneTrust, CookieBot, etc.) and cannot afford to disrupt the consent signal chain
- You have multiple GA4 destinations (e.g., a main GA4 property + a dev/staging property) and replacing the base tag would break the routing logic
- You have GA4 Event tags that are tightly coupled to the existing GA4 Configuration tag and retesting them all is not feasible
- You are implementing ClickMint for a client and want to minimize blast radius
Use Approach 2 instead if your GTM setup is straightforward (no sGTM, simple Consent Mode, few GA4 Event tags) — Approach 2 is simpler to set up and maintain.
How It Works
Understanding the mechanism before you configure it makes troubleshooting much easier.
Standard GA4 event dispatch (Approaches 1 and 2):
ClickMint script → gtag('event', ...) → GA4 library → hit sent to GA4
GTM Serverless event dispatch (Approach 3):
ClickMint script → gtag('event', ...) → dataLayer.push(arguments)
↓
GTM Custom Event trigger fires
↓
GA4 Event tag reads parameters from Data Layer Variables
↓
Hit sent to GA4 via your existing Google Tag
The ClickMint script already handles the gap: if your site uses GTM's managed GA4 adapter (meaning window.gtag doesn't exist as a standalone function), ClickMint polyfills it from the dataLayer. The gtag('event', ...) call becomes a dataLayer.push() — which GTM picks up via the trigger you'll configure below.
Prerequisites
Before starting:
- GTM container access — Editor or Publish permission.
- GA4 Measurement ID — found in GA4 → Admin → Data Streams → Web → Measurement ID. Format:
G-XXXXXXXXXX. - ClickMint Org ID — found in ClickMint dashboard → Settings → Organization. Use only the part after
org_in script URLs. - Existing Google Tag / GA4 Configuration tag — stays in place; do not modify it.
Setup
The setup has four parts. You'll build the pieces in dependency order: variables first (referenced by tags), then the trigger (referenced by the event tag), then the tags.
Part A — Tags to Create
Tag 1: cm script - serverless
cm script - serverlessThis tag loads the ClickMint experiment script.
- Go to Tags → New.
- Name:
cm script - serverless - Tag Type: Custom HTML
- HTML — paste the ClickMint snippet, replacing
YOUR_ORG_ID:
<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>- Check Support document.write — leave it unchecked.
- Triggering: Initialization - All Pages
- Click Save.
Tag 2: cm event tracking - serverless
cm event tracking - serverlessThis tag sends the cm_tracking event to GA4 through your existing Measurement ID.
-
Go to Tags → New.
-
Name:
cm event tracking - serverless -
Tag Type: Google Analytics: GA4 Event
-
Measurement ID: enter your
G-XXXXXXXXXX(the same ID used in your existing Google Tag)At this point GTM will show "Google tag found in this container" — this is expected and correct. It means the event will be routed through your existing Google Tag configuration.
-
Event Name:
cm_tracking -
Event Parameters — add the following rows:
Parameter Name Value event_type{{cm dl event type}}experiment_id{{cm dl experiment id}}experiment_mode{{cm dl experiment mode}}experiment_variant{{cm dl experiment variant}}outcome_id{{cm dl outcome id}}outcome_index{{cm dl outcome index}}outcome_type{{cm dl outcome type}}page_path{{Page Path}}{{Page Path}}is a GTM built-in variable — no configuration needed. -
User Properties — add one row:
Property Name Value experiment_id{{cm dl up experiment id}}This user property is what enables conversion attribution. GA4 attaches it to all subsequent events in the session — including
purchase— so ClickMint can attribute conversions to the correct variant. See Why the User Property Matters. -
Triggering:
cm tracking event(the trigger you'll create in Part B) -
Click Save.
Part B — Trigger to Create
- Go to Triggers → New.
- Name:
cm tracking event - Trigger Type: Custom Event
- Event name:
cm_tracking - This trigger fires on: All Custom Events
- Click Save.
Part C — Variables to Create
Create the following 9 User-Defined Variables. All except cm_tracking are Data Layer Variable type with Data Layer Version 2.
Data Layer Variables (8 variables)
For each row below:
- Go to Variables → New (under User-Defined Variables).
- Name: as shown in the "Variable Name" column.
- Variable Type: Data Layer Variable.
- Data Layer Variable Name: as shown in the "Data Layer Variable Name" column.
- Data Layer Version: Version 2.
- Click Save.
| Variable Name | Data Layer Variable Name | What it captures |
|---|---|---|
cm dl event type | eventModel.event_type | Whether this is a variant_loaded, control, or error event |
cm dl experiment id | eventModel.experiment_id | The visitor's ClickMint tracking ID |
cm dl experiment mode | eventModel.experiment_mode | production or preview |
cm dl experiment variant | eventModel.experiment_variant | The variant token (e.g., 42_1) |
cm dl outcome id | eventModel.outcome_id | Composite outcome ID (e.g., 42_1) |
cm dl outcome index | eventModel.outcome_index | Numeric variant index as a string |
cm dl outcome type | eventModel.outcome_type | redirect, repaint, control, or error message |
cm dl up experiment id | user_properties.experiment_id | Experiment ID for the GA4 User Property |
Custom Event Variable (1 variable)
- Go to Variables → New.
- Name:
cm_tracking - Variable Type: Custom Event
- No additional configuration required — GTM will automatically capture the custom event name.
- Click Save.
Part D — Tags to Keep
Do not modify the following tags. They stay exactly as they are:
- Your existing Google Tag (type: Google Tag) or GA4 Configuration tag (type: Google Analytics: GA4 Configuration) — this continues to manage the GA4 base configuration and consent signals.
- Any GA4 Event tags you have for e-commerce (
purchase,add_to_cart,begin_checkout, etc.) — these are unaffected. - Any Elevar, Littledata, or other third-party data layer tags — these are unaffected.
Data Layer Variable Reference
This table is the authoritative reference for all 8 event-scoped Data Layer Variables. The "Data Layer Variable Name" column must match exactly (case-sensitive) when creating variables manually.
| GTM Variable Name | Data Layer Variable Name | Scope | Description |
|---|---|---|---|
cm dl event type | eventModel.event_type | Event | variant_loaded | control | error |
cm dl experiment id | eventModel.experiment_id | Event | Visitor's ClickMint tracking ID (cm_...) |
cm dl experiment mode | eventModel.experiment_mode | Event | production | preview |
cm dl experiment variant | eventModel.experiment_variant | Event | Variant token (e.g., 42_1 for variant, c7761e58 hash for control) |
cm dl outcome id | eventModel.outcome_id | Event | Composite outcome ID (e.g., 42_1) |
cm dl outcome index | eventModel.outcome_index | Event | Numeric variant index as string (e.g., "1") |
cm dl outcome type | eventModel.outcome_type | Event | redirect | repaint | control | error message |
cm dl up experiment id | user_properties.experiment_id | User | Experiment ID for GA4 user property — used for conversion attribution |
Note on
{{Page Path}}: This parameter is captured using GTM's built-in{{Page Path}}variable and does not require a custom Data Layer Variable.
Why the User Property Matters
The experiment_id user property — mapped via cm dl up experiment id — is the foundation of ClickMint's conversion attribution.
When the cm_tracking event fires, the GA4 Event tag sets experiment_id as a user property. GA4 automatically attaches this user property to every subsequent event in the session, including purchase. Later, ClickMint's backend queries the GA4 Data API for purchase events filtered by experiment_id — this is how it attributes a sale to the variant (or control) a visitor saw earlier on the page.
If this user property is omitted or misconfigured, conversion data will not appear in ClickMint. Impressions (experiment exposures) will still be reported correctly, but conversion counts will remain at zero.
To verify the user property is being set:
- In GA4 DebugView, click the
cm_trackingevent. - Scroll to User Properties — confirm
experiment_idappears with acm_...value.
Verifying Your Setup
Step 1 — GTM Preview Mode
- In GTM, click Preview.
- Visit a page with an active ClickMint experiment.
- In Tag Assistant, confirm:
cm script - serverlessfires on Initialization - All Pages ✓- After the ClickMint script runs:
cm event tracking - serverlessfires on thecm_trackingCustom Event ✓ - Your existing Google Tag continues to fire as before ✓
Step 2 — Confirm variables resolve
In GTM Preview, click on the cm tracking event trigger fire event. Under Variables, confirm the cm dl * variables show resolved values (not undefined).
If any variable shows undefined, check the Data Layer Variable Name spelling in that variable's configuration — it must match the table in Part C exactly.
Step 3 — GA4 DebugView
- In GA4, go to Admin → DebugView.
- Navigate to a page with an active experiment.
- Look for the
cm_trackingevent. - Expand it and verify all event parameters are present.
- Check User Properties — confirm
experiment_idis set with acm_...value.
Step 4 — Confirm no duplicate events
In the browser console:
window.dataLayer.filter((e) => e.event === 'cm_tracking').lengthThis should return 1 per page load. If it returns 2, the ClickMint script may be loading twice — check for duplicate cm script tags in your container.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
cm event tracking - serverless tag never fires | cm tracking event trigger not configured correctly | Confirm trigger type is Custom Event and event name is exactly cm_tracking |
Variables show undefined in GTM Preview | Data Layer Variable Name typo | Check each variable's DL variable name against the reference table — names are case-sensitive |
cm_tracking appears in DebugView but experiment_id user property is missing | cm dl up experiment id variable misconfigured | Confirm the Data Layer Variable Name is exactly user_properties.experiment_id (Version 2) |
cm_tracking fires but event_type is error | ClickMint script loaded but no active experiment on URL | Create or activate an experiment for this URL in the ClickMint dashboard |
| Conversions show as zero in ClickMint after 48h | GA4 custom dimensions not registered | Register experiment_id, outcome_id, outcome_index as user-scoped custom dimensions in GA4 Admin |
| Existing GA4 tags broken after import | Import used "Overwrite" instead of "Rename" | Re-import using Merge → Rename conflicts, or restore from a GTM workspace version |
cm_tracking event missing entirely | CM script not loading | Check the network tab for a request to experiments.api.clickmint.com — confirm it returns 200 with JavaScript content |
Updated about 4 hours ago
