Skip to main content

Debug Mode and validation feedback

Debug Mode gives you detailed feedback on how your events match the published schema. Use it while implementing tracking to inspect field types, required values and unknown fields directly in the response.

Add the debug headers below, send an event and read its validation results. With Server-GTM, you can also return this feedback through JSON Client to the browser and display it in the console.

Enable Debug Mode​

Sender to PlatformAdditional debug headers
Backend or Server-GTM with a server keyX-DDA-Debug: true
Direct browser request with a browser keyX-DDA-Debug: true and X-DDA-Debug-Token: <token-for-this-browser-key>

Keep the normal Authorization, Content-Type and schema-version headers. The debug token is separate from the browser ingestion key. The flag must have the literal value true. It requests details for that request, rather than enabling a persistent mode for the entire environment.

Server request headers:

Authorization: Bearer <server-key>
Content-Type: application/json
X-DDA-Event-Schema-Version: <published-version>
X-DDA-Debug: true

Direct browser request headers:

Authorization: Bearer <browser-key>
Content-Type: application/json
X-DDA-Event-Schema-Version: <published-version>
X-DDA-Debug: true
X-DDA-Debug-Token: <debug-token-for-this-browser-key>

Add X-DDA-Debug: true to your request. With a server key, that header is sufficient. With a browser key, also send X-DDA-Debug-Token using the debug token for that exact key from Ingestion keys. A token for another key in the same environment does not work.

Use the browser token only in a controlled debugging session. Do not embed it in code distributed to every visitor. A cookie or tag-manager preview flag alone does not enable API diagnostics. Your integration must send the headers.

View validation feedback​

Send an event with the debug headers and open the response in the browser's Network panel, your tag manager's preview or your HTTP client's response viewer. results[].validation.status shows the validation outcome for each event. With debug enabled, results[].validation.issues adds details about warnings and errors, for example:

{
"severity": "warning",
"code": "schema_unknown_field",
"path": "events[0].campaign.internal",
"message": "The field is not part of this event schema version and was discarded.",
"observedType": "string",
"action": "removed"
}

The path identifies the affected field. Compare it with the published version used by the sender, not only the current draft. Diagnostics may be truncated. Debug does not change acceptance rules or activate validation mode. A missing or invalid browser debug token leaves the compact response in place without stopping event ingestion.

Interpret the event result​

results[].statusMeaningNext step
sampled_for_schema_discoveryUsed to discover structureReview and publish the schema, then update the sender
validated_onlyChecked without collectionConfigure and test the destination, then send fresh events
queuedAccepted for processingVerify destination status and warehouse delivery
duplicateIdentical event already accepted within the deduplication windowCheck the original event and your trigger or retry behavior
filteredExcluded by bot or consent rulesInspect reason and the relevant mapped event fields
rejectedThis event was not acceptedInspect code and validation details, then correct it

validation.status is separate from the processing status. It can be passed, warning, failed or not_run. A warning can mean an unknown field was removed. A passed schema check does not guarantee warehouse delivery. Check every result in a batch rather than treating HTTP 202 as success for every event.

Return validation feedback through Server-GTM​

This integration uses three components with different roles:

ComponentRuns inRole
JSON TagBrowser, typically through Web-GTMSends the event to your tagging server and receives its response
JSON ClientServer-GTM, as a client templateReceives the incoming request, prepares Event Data and makes it available to server tags
JSON Server TagServer-GTM, as a tag templateSends the event to Platform and passes its response back to JSON Client

This lets you bring Platform validation feedback back to the browser during development:

Browser: JSON Tag → Server-GTM: JSON Client → JSON Server Tag → Platform
Browser: JSON Tag ← Server-GTM: JSON Client ← JSON Server Tag ← validation response
  1. Configure JSON Tag in the browser, typically through Web-GTM, to send events to your tagging server. In Server-GTM, configure JSON Client to receive requests at that path and prepare their Event Data. Configure JSON Server Tag to run on those events and forward them to Platform with its server key and schema version.
  2. In the tag's Custom Request Headers, add X-DDA-Debug with value true for your controlled development or preview requests. No Platform browser debug token is needed on this server-to-server hop.
  3. Under Response Settings, enable Send Response to JSON Client. Set Response Key to a recognizable value, such as platform_validation.
  4. Trigger a test event through JSON Tag. Inspect the response from your tagging server. Its tag response contains Platform's requestId and results.
  5. Read results[].validation.issues to see field-level feedback while developing. Also check results[].status, even if Server-GTM marks the HTTP call successful.

JSON Server Tag already implements the response forwarding option. You do not need to modify its template code. See its Response Settings documentation.

The current JSON Client returns an array under responses, including for a single event. Each entry contains its tag data under tags. JSON Tag can also expose this data in its Data Layer push. See JSON Client response forwarding and batch responses.

This example groups results in the browser console, highlights queued events and shows validation issues as a table. It runs in the web container, after JSON Tag has received the response from your tagging server.

  1. Enable Send Response to JSON Client in JSON Server Tag. For this script, set Response Key to dda. If you used platform_validation above, either change that setting or replace response.tags.dda in the script with response.tags.platform_validation.
  2. In Web-GTM Preview, find the Data Layer event where JSON Tag supplies the returned response. Create a Data Layer Variable pointing to the complete parsed JSON Client response object, including responses. Name the GTM variable Jsonclient Response (Data Layer Variable) to match the reference below. The variable name is not the Data Layer path. Select that path from your actual push.
  3. Create a Custom HTML tag in the web container and paste the script below.
  4. Enable Push Response in Data Layer in JSON Tag Settings. Create a Custom Event trigger with event name jsonclientResponse (case-sensitive). You can name the trigger JSON Client Response. If you changed Data Layer Event Name in JSON Tag Settings, use that configured value instead. Trigger on the response, not the earlier outgoing tracking event.
  5. Send an event, open the browser console and expand its result group.

Only show console output in debug sessions​

Enable the built-in Debug Mode variable under Variables → Configure in the web container. It indicates GTM preview/debug mode. Add an exception to the console tag:

SettingValue
Firing triggerCustom Event jsonclientResponse
Exception triggerCustom Event jsonclientResponse, Some Custom Events
Exception condition{{Debug Mode}} does not equal true

Attach the exception under the tag's Exceptions. Both triggers evaluate the same response event. Outside preview/debug mode, the exception blocks the console tag.

Alternatively, create a 1st Party Cookie variable for your own debug cookie, for example tracking_debug. Use a custom-event exception for the same response event with the condition that this variable does not equal 1. Set the cookie to 1 for your debug session. An absent cookie also leaves console output blocked. If either GTM preview or the cookie should enable output, put both negative conditions in one exception: Debug Mode does not equal true and cookie does not equal 1.

These conditions control the console tag only. They do not enable Platform's X-DDA-Debug header or the server-side response forwarding. Configure those separately. Check in Preview that the tag fires when your chosen debug condition is enabled and is blocked when it is disabled.

References: JSON Tag Settings response configuration, GTM built-in variables and trigger exceptions.

The {{...}} reference is a GTM variable, not standalone JavaScript. Adjust it if your variable has another name. The script only reads and displays the response. It does not send events or enable the debug headers for you.

<script>
(function () {
var client = {{Jsonclient Response (Data Layer Variable)}};
var con = window.console;

if (!con || !client || !Array.isArray(client.responses)) return;

var successStyle =
"background: #dcfce7; color: #166534; padding: 3px 8px; " +
"border-radius: 4px; font-weight: bold;";
var warningStyle =
"background: #ffedd5; color: #9a3412; padding: 3px 8px; " +
"border-radius: 4px; font-weight: bold;";

client.responses.forEach(function (response, responseIndex) {
var feedback = response && response.tags && response.tags.dda;
if (!feedback) return;
var requestId = feedback.requestId || "unknown";

if (!Array.isArray(feedback.results)) {
con.log("%c[Drag & Drop Analytics] NO EVENT RESULTS", warningStyle, {
requestId: requestId,
status: feedback.status,
code: feedback.code,
message: feedback.message
});
return;
}

feedback.results.forEach(function (result) {
if (!result) return;
var validation = result.validation || {};
var issues = Array.isArray(validation.issues) ? validation.issues : [];
var passed = validation.status === "passed" &&
issues.length === 0 && !validation.truncated;
var success = passed && result.status === "queued";
var headline;

if (success) {
headline = "✓ QUEUED";
} else if (result.status === "rejected" || validation.status === "failed") {
headline = "⚠ FAILED";
} else if (issues.length || validation.status === "warning" || validation.truncated) {
headline = "⚠ VALIDATION ISSUES";
} else {
headline = (result.status || "UNKNOWN").toUpperCase();
}

var label = "[Drag & Drop Analytics] " + headline +
" | Response " + responseIndex +
" | Event index " + result.index +
" | " + result.status +
" | Validation: " + (validation.status || "unknown");
con.groupCollapsed("%c" + label, success ? successStyle : warningStyle);
con.log("Request ID:", requestId);

if (issues.length) {
var rows = issues.map(function (issue) {
return {
Severity: issue.severity || "",
Code: issue.code || "",
Path: issue.path || "",
Message: issue.message || "",
ExpectedType: issue.expectedType || "",
ObservedType: issue.observedType || "",
Action: issue.action || ""
};
});
if (con.table) con.table(rows);
else con.log(rows);
}
if (validation.truncated) {
con.warn("Diagnostics were truncated. Additional issues are not shown.");
}
if (passed) {
con.log(result.status === "queued"
? "✓ Valid, with no validation issues. Added to the queue."
: "✓ Validation passed with no validation issues.");
} else if (!issues.length && !validation.truncated) {
if (validation.status === "not_run") {
con.info("Validation was not performed, e.g. during schema discovery.");
} else {
con.warn("Validation status:", validation.status || "unknown",
"| No issue details included in the response.");
}
}
if (result.status === "rejected") {
con.error("Event rejected:", result.code || "no error code provided");
} else if (result.status === "filtered") {
con.info("Event filtered:", result.reason || "no reason provided");
} else if (result.status === "duplicate") {
con.info("Duplicate detected. Not added to the queue again.");
}
con.groupEnd();
});
});
})();
</script>

Green QUEUED means validation passed and the event was added to the queue. It does not confirm warehouse delivery. Other groups show validation warnings, rejections, filtering, duplicates or validation-only results. Truncated diagnostics are explicitly marked. Empty detail columns mean that the response did not include that property. The current Platform diagnostics do not provide expectedType, so that optional column remains empty.

For detailed field feedback, enable the server-side debug header as described above. The script cannot recover details that were not included in the response.

Check the feedback loop during development​

In a test environment, send a valid event, then one with a deliberately wrong type for a required field. Confirm that the latter returns rejected, validation failed and an issue identifying the field. Fix it and send a fresh event. An extra undeclared field can produce a warning and be removed without rejecting the whole event. This makes it possible to distinguish warnings from failures before publishing tracking changes.

Restrict detailed response forwarding to your intended debugging audience. A debug header added unconditionally by the server tag can expose diagnostics to every caller receiving its response. Remove or condition that header and response forwarding when leaving the development workflow. Keep the server key on the server.

Diagnose HTTP errors​

HTTP statusWhat to check
400JSON shape, required fields, field types and schema-version header. Read the error code or per-event results
401Missing, invalid, expired or revoked ingestion key
403Browser origin allowlist, key type and actual request origin
409Producer event ID reused with conflicting content
413Event size, total request size or batch count
429Rate limit or quota. Follow response information and Retry-After when present
503Temporary ingestion or processing unavailability. Preserve stable event IDs for bounded retries

Do not retry every 4xx response unchanged. Fix its cause. A batch may contain both accepted and rejected events, so the HTTP status alone is not the full diagnosis.

When the warehouse or report is empty​

  1. Confirm the event went to the intended environment and destination.
  2. Inspect its result. Discovery and validation-only events will not be delivered later.
  3. For filtered, check consent mappings, destination requirements and the mapped User-Agent used for bot detection.
  4. For queued, check the destination connection and Collection needs attention hints. Acceptance is not a warehouse acknowledgement.
  5. If the event is in the warehouse, check the Explorer data source, read permissions, date range, timezone, selected metric and filters.

After a change, send a new event to see the updated validation feedback.