Google Analytics 4
Deze gids behandelt methoden om Google Analytics 4 (GA4)-events te onderscheppen. Kies de methode die het beste bij je behoeften past.
Methode 1 en 2 zijn voor web tracking met client-side GTM, Methode 3 is voor web tracking met directe gtag (zonder GTM), en Methode 4 is voor server-side tracking (server-side GTM).
Methode 1: GA4-verzoeken dupliceren in GTM (aanbevolen)
Bij deze methode blijft je bestaande GA4-opstelling intact, terwijl events naar een custom endpoint worden gedupliceerd. Je data blijft gewoon naar Google Analytics stromen.
Stappen:
-
Open Google Tag Manager
- Navigeer naar je GTM-container
- Ga naar de sectie Tags
-
Maak een Custom HTML Tag
- Klik op New om een nieuwe tag te maken
- Kies Custom HTML als tagtype
- Noem hem:
D8A GA4 Duplicator
-
Voeg je onderscheppingscode toe
- Plak je hieronder gegenereerde custom code in het HTML-veld
De duplicator kopieert GA4-trackingverzoeken naar je endpoint terwijl de originele Google Analytics-verzoeken intact blijven. Hij doet dit door veelvoorkomende request-mechanismen te onderscheppen (XMLHttpRequest, fetch, navigator.sendBeacon en src-toewijzingen van scripts).
Gebruik de geminificeerde snippet voor productie, of de niet-geminificeerde versie voor controle. Je kunt de volledige implementatie ook bekijken in de broncode.
- Geminificeerd (voor productie)
- Niet-geminificeerd (voor controle)
<script>
var trackingURL = "https://global.t.d8a.tech/<property_id>/g/collect"; // Replace it with your tracking URL
/* ga4-duplicator - built 2026-03-22T06:26:46.438Z */
"use strict";
(() => {
// src/version.ts
var version = "dev-26-03" ? "dev-26-03" : devVersionUtc();
// src/ga4-duplicator.ts
window.createGA4Duplicator = function(options) {
class FetchInterceptor {
install(ctx) {
const originalFetch = window.fetch;
window.fetch = function(resource, config) {
const requestUrl = typeof resource === "string" ? resource : resource instanceof URL ? resource.toString() : resource.url;
const method = config && config.method || resource.method || "GET";
if (ctx.isTargetUrl(requestUrl)) {
const upperMethod = (method || "GET").toUpperCase();
let prepareBodyPromise = Promise.resolve(void 0);
if (upperMethod === "POST") {
if (config && Object.prototype.hasOwnProperty.call(config, "body")) {
prepareBodyPromise = Promise.resolve(config.body);
} else if (typeof Request !== "undefined" && resource instanceof Request) {
try {
const clonedReq = resource.clone();
prepareBodyPromise = clonedReq.blob().catch(() => void 0);
} catch (e) {
prepareBodyPromise = Promise.resolve(void 0);
}
}
}
const originalPromise = originalFetch.apply(this, arguments);
const duplicateUrl = ctx.buildDuplicateUrl(requestUrl);
const convertToGet = ctx.getConvertToGet(requestUrl);
if (upperMethod === "GET") {
originalFetch(duplicateUrl, {
method: "GET",
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug) console.error("gtm interceptor: error duplicating GET fetch:", error);
});
} else if (upperMethod === "POST") {
prepareBodyPromise.then((dupBody) => {
if (convertToGet) {
let bodyStr = "";
if (typeof dupBody === "string") {
bodyStr = dupBody;
} else if (dupBody instanceof Blob) {
originalFetch(duplicateUrl, {
method: "POST",
body: dupBody,
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug)
console.error(
"gtm interceptor: error duplicating POST fetch (convert_to_get with Blob):",
error
);
});
return;
}
const lines = bodyStr.split("\n");
let sentAny = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line) {
const mergedUrl = ctx.buildDuplicateUrl(requestUrl);
const urlWithMergedLine = mergeBodyLineWithUrl(mergedUrl, line);
originalFetch(urlWithMergedLine, {
method: "GET",
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug)
console.error(
"gtm interceptor: error duplicating GET fetch (from convert_to_get):",
error
);
});
sentAny = true;
}
}
if (!sentAny) {
originalFetch(duplicateUrl, {
method: "GET",
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug)
console.error(
"gtm interceptor: error duplicating GET fetch (empty body convert_to_get):",
error
);
});
}
} else {
originalFetch(duplicateUrl, {
method: "POST",
body: dupBody,
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug)
console.error("gtm interceptor: error duplicating POST fetch:", error);
});
}
});
}
return originalPromise;
}
return originalFetch.apply(this, arguments);
};
}
}
class XhrInterceptor {
install(ctx) {
const originalXHROpen = XMLHttpRequest.prototype.open;
const originalXHRSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function(method, url) {
this._requestMethod = method;
this._requestUrl = url;
return originalXHROpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function(body) {
if (this._requestUrl && ctx.isTargetUrl(this._requestUrl)) {
const originalResult = originalXHRSend.apply(this, arguments);
try {
const method = (this._requestMethod || "GET").toUpperCase();
const duplicateUrl = ctx.buildDuplicateUrl(this._requestUrl);
const convertToGet = ctx.getConvertToGet(this._requestUrl);
if (method === "GET") {
fetch(duplicateUrl, {
method: "GET",
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug) console.error("gtm interceptor: error duplicating GET xhr:", error);
});
} else if (method === "POST") {
if (convertToGet) {
let bodyStr = "";
if (typeof body === "string") {
bodyStr = body;
} else if (body && typeof body === "object") {
try {
bodyStr = String(body);
} catch (e) {
bodyStr = "";
}
}
const lines = bodyStr.split("\n");
let sentAny = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line) {
const mergedUrl = ctx.buildDuplicateUrl(this._requestUrl);
const urlWithMergedLine = mergeBodyLineWithUrl(mergedUrl, line);
fetch(urlWithMergedLine, {
method: "GET",
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug)
console.error(
"gtm interceptor: error duplicating GET xhr (from convert_to_get):",
error
);
});
sentAny = true;
}
}
if (!sentAny) {
fetch(duplicateUrl, {
method: "GET",
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug)
console.error(
"gtm interceptor: error duplicating GET xhr (empty body convert_to_get):",
error
);
});
}
} else {
fetch(duplicateUrl, {
method: "POST",
body,
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug)
console.error("gtm interceptor: error duplicating POST xhr:", error);
});
}
}
} catch (dupErr) {
if (ctx.debug) console.error("gtm interceptor: xhr duplication failed:", dupErr);
}
return originalResult;
}
return originalXHRSend.apply(this, arguments);
};
}
}
class BeaconInterceptor {
install(ctx) {
if (!navigator.sendBeacon) return;
const originalSendBeacon = navigator.sendBeacon;
navigator.sendBeacon = function(url, data) {
if (ctx.isTargetUrl(url)) {
const originalResult = originalSendBeacon.apply(this, arguments);
try {
const duplicateUrl = ctx.buildDuplicateUrl(url);
const convertToGet = ctx.getConvertToGet(url);
if (convertToGet) {
let bodyStr = "";
if (typeof data === "string") {
bodyStr = data;
} else if (data && typeof data === "object") {
try {
bodyStr = String(data);
} catch (e) {
bodyStr = "";
}
}
const lines = bodyStr.split("\n");
let sentAny = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line) {
const mergedUrl = ctx.buildDuplicateUrl(url);
const urlWithMergedLine = mergeBodyLineWithUrl(mergedUrl, line);
fetch(urlWithMergedLine, {
method: "GET",
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug)
console.error(
"gtm interceptor: error duplicating GET beacon (from convert_to_get):",
error
);
});
sentAny = true;
}
}
if (!sentAny) {
fetch(duplicateUrl, {
method: "GET",
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug)
console.error(
"gtm interceptor: error duplicating GET beacon (empty body convert_to_get):",
error
);
});
}
} else {
originalSendBeacon.call(navigator, duplicateUrl, data);
}
} catch (e) {
if (ctx.debug) console.error("gtm interceptor: error duplicating sendBeacon:", e);
}
return originalResult;
}
return originalSendBeacon.apply(this, arguments);
};
}
}
class ScriptInterceptor {
install(ctx) {
try {
const scriptSrcDescriptor = Object.getOwnPropertyDescriptor(
HTMLScriptElement.prototype,
"src"
);
const originalScriptSrcSetter = scriptSrcDescriptor && scriptSrcDescriptor.set;
const originalScriptSrcGetter = scriptSrcDescriptor && scriptSrcDescriptor.get;
const originalScriptSetAttribute = HTMLScriptElement.prototype.setAttribute;
const duplicateIfGA4Url = (urlString) => {
try {
if (!ctx.isTargetUrl(urlString)) return;
fetch(ctx.buildDuplicateUrl(urlString), {
method: "GET",
keepalive: true,
credentials: "include"
}).catch((error) => {
if (ctx.debug) console.error("gtm interceptor: error duplicating script GET:", error);
});
} catch (e) {
}
};
if (originalScriptSrcSetter && originalScriptSrcGetter) {
const setter = originalScriptSrcSetter;
const getter = originalScriptSrcGetter;
Object.defineProperty(HTMLScriptElement.prototype, "src", {
configurable: true,
enumerable: true,
get: function() {
return getter.call(this);
},
set: function(value) {
try {
const last = this.__ga4LastSrcDuplicated;
if (value && value !== last) {
duplicateIfGA4Url(String(value));
this.__ga4LastSrcDuplicated = String(value);
}
const self = this;
const onloadOnce = function() {
try {
const finalUrl = self.src;
if (finalUrl && finalUrl !== self.__ga4LastSrcDuplicated) {
duplicateIfGA4Url(finalUrl);
self.__ga4LastSrcDuplicated = finalUrl;
}
} catch (e) {
}
self.removeEventListener("load", onloadOnce);
};
this.addEventListener("load", onloadOnce);
} catch (e) {
}
setter.call(this, value);
}
});
}
HTMLScriptElement.prototype.setAttribute = function(name, value) {
try {
if (String(name).toLowerCase() === "src") {
const v = String(value);
const last = this.__ga4LastSrcDuplicated;
if (v && v !== last) {
duplicateIfGA4Url(v);
this.__ga4LastSrcDuplicated = v;
}
const selfAttr = this;
const onloadOnceAttr = function() {
try {
const finalUrlAttr = selfAttr.src;
if (finalUrlAttr && finalUrlAttr !== selfAttr.__ga4LastSrcDuplicated) {
duplicateIfGA4Url(finalUrlAttr);
selfAttr.__ga4LastSrcDuplicated = finalUrlAttr;
}
} catch (e) {
}
selfAttr.removeEventListener("load", onloadOnceAttr);
};
this.addEventListener("load", onloadOnceAttr);
}
} catch (e) {
}
return originalScriptSetAttribute.apply(this, arguments);
};
} catch (e) {
}
}
}
if (window.__ga4DuplicatorInitialized) {
if (options.debug) console.warn("GA4 Duplicator: already initialized.");
return;
}
const destinations = [];
if (options.destinations && Array.isArray(options.destinations)) {
for (let i = 0; i < options.destinations.length; i++) {
const dest = options.destinations[i];
destinations.push({
measurement_id: dest.measurement_id,
server_container_url: dest.server_container_url,
convert_to_get: dest.convert_to_get !== void 0 ? dest.convert_to_get : options.convert_to_get
});
}
}
if (options.server_container_url) {
destinations.push({
measurement_id: "*",
server_container_url: options.server_container_url,
convert_to_get: options.convert_to_get
});
}
if (destinations.length === 0) {
console.error("GA4 Duplicator: either server_container_url or destinations array is required");
return;
}
function normalizePath(p) {
p = String(p || "");
p = p.replace(/\/+$/, "");
return p === "" ? "/" : p;
}
function matchesId(pattern, id) {
if (!pattern || pattern === "*") return true;
try {
const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
return new RegExp("^" + regexStr + "$", "i").test(id);
} catch (e) {
return pattern.toLowerCase() === id.toLowerCase();
}
}
function ensureBareQueryFlag(url, flag) {
const u = String(url || "");
const f = String(flag || "").trim();
if (!u || !f) return u;
const hashIdx = u.indexOf("#");
const beforeHash = hashIdx >= 0 ? u.slice(0, hashIdx) : u;
const hash = hashIdx >= 0 ? u.slice(hashIdx) : "";
const qIdx = beforeHash.indexOf("?");
const base = qIdx >= 0 ? beforeHash.slice(0, qIdx) : beforeHash;
const rawQuery = qIdx >= 0 ? beforeHash.slice(qIdx + 1) : "";
const parts = rawQuery ? rawQuery.split("&").map((p) => p.trim()).filter(Boolean) : [];
const kept = [];
for (let i = 0; i < parts.length; i++) {
const p = parts[i];
if (p === f) continue;
if (p.startsWith(f + "=")) continue;
kept.push(p);
}
const newQuery = kept.length > 0 ? kept.join("&") + "&" + f : f;
return base + "?" + newQuery + hash;
}
function getMeasurementId(url) {
try {
const parsed = new URL(url, location.href);
return parsed.searchParams.get("tid") || parsed.searchParams.get("id") || "";
} catch (e) {
const match = url.match(/[?&](?:tid|id)=([^&?#]+)/);
return match ? decodeURIComponent(match[1]) : "";
}
}
function getDestinationForId(id) {
for (let i = 0; i < destinations.length; i++) {
if (matchesId(destinations[i].measurement_id, id)) {
return destinations[i];
}
}
return null;
}
function mergeBodyLineWithUrl(originalUrl, bodyLine) {
try {
const url = new URL(originalUrl, location.href);
const lineParams = new URLSearchParams(bodyLine);
for (const [key] of lineParams.entries()) {
url.searchParams.delete(key);
}
for (const [key, value] of lineParams.entries()) {
url.searchParams.append(key, value);
}
return ensureBareQueryFlag(url.toString(), "richsstsse");
} catch (e) {
const urlWithoutQuery = originalUrl.split("?")[0];
const originalParams = originalUrl.match(/\?(.*)/) ? originalUrl.match(/\?(.*)/)[1] : "";
const merged = originalParams + (originalParams && bodyLine ? "&" : "") + bodyLine;
return ensureBareQueryFlag(urlWithoutQuery + (merged ? "?" + merged : ""), "richsstsse");
}
}
function getDuplicateEndpointUrl(dest) {
const trackingURL = String(dest.server_container_url || "").trim();
const u = new URL(trackingURL, location.href);
u.search = "";
u.hash = "";
return u;
}
function isTargetUrl(url) {
if (!url || typeof url !== "string") return false;
try {
const parsed = new URL(url, location.href);
for (let i = 0; i < destinations.length; i++) {
const duplicateTarget = getDuplicateEndpointUrl(destinations[i]);
if (parsed.origin === duplicateTarget.origin && normalizePath(parsed.pathname) === normalizePath(duplicateTarget.pathname)) {
return false;
}
}
const params = parsed.searchParams;
const hasGtm = params.has("gtm");
const hasTagExp = params.has("tag_exp");
const measurementId = params.get("tid") || params.get("id") || "";
const isMeasurementIdGA4 = /^G-[A-Z0-9]+$/i.test(measurementId);
return hasGtm && hasTagExp && isMeasurementIdGA4;
} catch (e) {
if (typeof url === "string") {
for (let j = 0; j < destinations.length; j++) {
try {
const target = getDuplicateEndpointUrl(destinations[j]);
const targetNoQuery = target.origin + target.pathname;
if (url.indexOf(targetNoQuery) !== -1) return false;
} catch (e2) {
}
}
const hasGtmFallback = url.indexOf("gtm=") !== -1;
const hasTagExpFallback = url.indexOf("tag_exp=") !== -1;
const idMatch = url.match(/[?&](?:tid|id)=G-[A-Za-z0-9]+/);
return !!(hasGtmFallback && hasTagExpFallback && idMatch);
}
return false;
}
}
function buildDuplicateUrl(originalUrl) {
const id = getMeasurementId(originalUrl);
const dest = getDestinationForId(id);
if (!dest) return "";
const dst = getDuplicateEndpointUrl(dest);
try {
const src = new URL(originalUrl, location.href);
dst.search = src.search;
dst.searchParams.set("_dtv", version);
dst.searchParams.set("_dtn", "gd");
} catch (e) {
}
return ensureBareQueryFlag(dst.toString(), "richsstsse");
}
function getConvertToGet(url) {
const id = getMeasurementId(url);
const dest = getDestinationForId(id);
return dest ? !!dest.convert_to_get : false;
}
const context = {
debug: !!options.debug,
isTargetUrl,
buildDuplicateUrl,
getConvertToGet
};
const interceptors = [
new FetchInterceptor(),
new XhrInterceptor(),
new BeaconInterceptor(),
new ScriptInterceptor()
];
for (let i = 0; i < interceptors.length; i++) {
try {
interceptors[i].install(context);
} catch (e) {
if (options.debug) console.error("GA4 Duplicator: failed to install interceptor", e);
}
}
window.__ga4DuplicatorInitialized = true;
};
})();
//# sourceMappingURL=gd.js.map
window.createGA4Duplicator({
server_container_url: trackingURL,
});
</script>
-
Sla de tag op
- Sla je D8A GA4 Duplicator-tag op zodat hij beschikbaar is wanneer je in de volgende stap de Google Tag configureert
- Let op: je hoeft aan deze tag geen trigger toe te voegen
-
Laat de duplicator vóór de Google Tag afvuren
- Open je Google Tag (je GA4-configuratietag)
- Klap Advanced Settings → Tag Sequencing uit
- Selecteer onder Fire a tag before Google Tag Name fires je D8A GA4 Duplicator-tag
-
Opslaan en publiceren
- Sla je tag op
- Dien de wijzigingen in en publiceer je container
Je kunt nu je web tracking-setup testen.
Methode 2: Alle GA4-verzoeken omleiden in GTM
⚠️ Waarschuwing: Deze methode stopt het verzenden van data naar je GA4-property. Gebruik dit alleen als je tracking volledig naar je d8a-instantie wilt omleiden.
Stappen:
-
Open Google Tag Manager
- Navigeer naar je GTM-container
- Ga naar de sectie Tags
-
Pas je Google Tag aan
- Zoek je bestaande Google Tag (GA4-configuratietag)
- Bewerk de tagconfiguratie
-
Wijzig de Server Container URL
- Voeg in de Configuration-instellingen van de tag een nieuwe parameter toe met de naam
server_container_url - Stel de waarde in op je d8a-trackingdomein, bijv.
https://example.org/notitieGoogle voegt automatisch
/g/collectaan deze waarde toe, dus neem/g/collectniet op inserver_container_url.
- Voeg in de Configuration-instellingen van de tag een nieuwe parameter toe met de naam
Methode 3: GA4-verzoeken rechtstreeks dupliceren met gtag
Deze methode dupliceert verzoeken op het niveau van de Google Tag (gtag) door service_container_url als extra bestemming toe te voegen.
Deze methode gaat ervan uit dat gtag al rechtstreeks in je HTML is geïnstalleerd (zonder web-GTM).
Stappen:
-
Bevestig je directe
gtag-opstelling- Controleer of de standaard Google tag-snippet al op je pagina aanwezig is (bijvoorbeeld in
<head>)
- Controleer of de standaard Google tag-snippet al op je pagina aanwezig is (bijvoorbeeld in
-
Behoud je bestaande GA4-config-aanroep
- Laat je primaire
gtag('config', 'G-XXXXXXX')-aanroep ongewijzigd
- Laat je primaire
-
Voeg een tweede config-aanroep toe met
service_container_url- Voeg nog een
gtag('config', ...)-aanroep toe voor dezelfde Google tag-ID - Stel
service_container_urlin op je d8a-endpoint-URL, bijvoorbeeld:https://global.t.d8a.tech/13370000-1984-0042-0069-c0ffee123456/g/collect - Voorbeeld:
- Voeg nog een
<script
async
src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"
></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
// Existing GA4 destination
gtag("config", "G-XXXXXXX");
// Additional destination for duplicated traffic
gtag("config", "<property_id>", {
service_container_url: "https://global.t.d8a.tech/<property_id>/g/collect",
});
</script>
Je web tracking-setup testen
-
Open de DevTools van je browser
- Ga naar het tabblad Network
- Filter op "collect" of je endpoint-domein
-
Activeer test-events
- Navigeer tussen pagina's, klik op knoppen, verstuur formulieren
- Let op uitgaande verzoeken
-
Verifieer de datastroom
- Methode 1: Controleer of zowel GA4 als je endpoint data ontvangen
- Methode 2: Controleer of alleen je endpoint data ontvangt
- Methode 3: Controleer of GA4-verkeer wordt gedupliceerd naar je
service_container_url-endpoint
-
Optioneel: gebruik de GTM Preview-modus (alleen Methode 1 en 2)
- Schakel de Preview-modus in GTM in
- Verifieer dat tags in de juiste volgorde afvuren
- Controleer op fouten in de console
Methode 4: Verzoeken dupliceren in Google Tag Manager server-side
Deze methode dupliceert GA4-verzoeken op het niveau van de server-side container, wat handig is voor server-side tracking-implementaties.
Deze methode gaat ervan uit dat je al een werkende GA4-client hebt geconfigureerd in je Google Tag Manager server-side container. Als je server-side GTM nog niet hebt opgezet, configureer dan eerst je GA4-client.
Stappen:
-
Maak een User-Agent-variabele
- Ga naar Variables in je server-side GTM-container
- Klik op New om een nieuwe variabele te maken
- Kies Request Header als variabeletype
- Stel de Variable Name in op:
User-Agent - Stel de Header Name in op:
User-Agent - Sla de variabele op
-
Maak een X-Forwarded-For-variabele
- Maak nog een nieuwe variabele
- Kies Request Header als variabeletype
- Stel de Variable Name in op:
X-Forwarded-For - Stel de Header Name in op:
X-Forwarded-For - Sla de variabele op
-
Voeg de JSON HTTP Request-tagtemplate toe
- Ga naar Templates in je server-side GTM-container
- Klik op Search Gallery
- Zoek naar en voeg de JSON HTTP request-tagtemplate uit de community gallery toe
-
Maak een nieuwe Tag
- Ga naar Tags en klik op New
- Kies de zojuist toegevoegde JSON HTTP request-tagtemplate
- Configureer de tag:
- Destination URL:
<your-d8a-instance-url>{{Request Path}}?{{Query String}}- Vervang
<your-d8a-installation-url>door je d8a-endpoint-URL (bijv.https://example.org) - Je voltooide Destination URL zou er bijvoorbeeld zo uit moeten zien:
https://example.org{{Request Path}}?{{Query String}}notitie{{Request Path}}en{{Query String}}zijn ingebouwde variabelen die beschikbaar zijn in server-side GTM.
- Vervang
- Destination URL:
- Voeg in de sectie Request Headers twee entries toe:
- Eerste entry:
- Key:
User-Agent - Value:
{{User-Agent}}
- Key:
- Tweede entry:
- Key:
X-Forwarded-For - Value:
{{X-Forwarded-For}}
- Key:
- Eerste entry:
-
Configureer de Trigger
- Selecteer in de sectie Triggering dezelfde trigger die je voor je GA4-verkeer gebruikt. Zo zorg je ervoor dat de tag afvuurt telkens wanneer GA4-events worden verwerkt
-
Opslaan en publiceren
- Sla je tag op
- Dien de wijzigingen in en publiceer je server-side container
Je server-side tracking-setup testen
Gebruik om je server-side opstelling te testen de debug-modus in Google Tag Manager server-side. Hiermee kun je verifiëren dat verzoeken correct naar je d8a-endpoint worden gedupliceerd. De uiteindelijke URL en de respons van de d8a-server zijn beschikbaar in het tabblad Console.
Liever een native tracker?
Als je bestaande GA4-tracking niet wilt onderscheppen en de voorkeur geeft aan een opstelling die onafhankelijk is van Google, gebruik dan onze speciale gtag-compatibele web tracker: Web tracker.