Module 09 · Debugging

Read the wire.
Trust the wire.

Reports lie, dashboards lie, your eyes lie. The hit that left the browser does not. Every debugging session in AA ends at the network panel — and starts the moment you stop trusting anything else.

Reading45 min
LabHit decoder
DifficultyCore
Pre-reqModules 03–06

1 · Debugging mindset

The wire is the truth. Everything else — Workspace, the Launch UI, your console logs, the analyst's screenshot — is downstream of the wire and can be corrupted by configuration, processing rules, classifications, or human misreading. When in doubt, read the wire.

Three rules to internalise:

  1. If it's not on the hit, it's not in the report. No exceptions.
  2. If it's on the hit but not in the report, processing rules or VISTA dropped it.
  3. If it's in the report but you didn't expect it, persistence or processing rules added it. eVars have memory.

2 · The network panel

Open DevTools → Network → filter b/ss (AppMeasurement) or interact (Web SDK).

What you seeWhat it means
A GET to …/b/ss/yourrsid/1/JS-…/s12345?...AppMeasurement hit (legacy)
A POST to …edge.adobedc.net/ee/interactWeb SDK event
Status 200 with response body containing "received":trueHit reached Adobe
Status 0 / redBlocked locally (ad blocker, CSP, network)
Status 408 / 502 / timeoutAdobe-side or transport issue — retry

For AppMeasurement, the entire hit is in the URL's query string. For the Web SDK, the payload is in the POST body — switch to the Payload tab to read it. Both are inspectable in plain text; nothing is encrypted at the application layer (HTTPS handles transport).

2.1 — Persist logs across navigations

In Chrome DevTools, check Network → Preserve log. Without it, every page navigation clears the log and you lose the prior hit's evidence — exactly when you want it most. Same in Firefox (Persist Logs) and Safari (Preserve Log in the Network settings menu).

3 · Anatomy of a hit URL

A typical AppMeasurement hit looks like this (line-broken for reading):

https://yourcorp.sc.omtrdc.net/b/ss/yourrsid/1/JS-2.22.0-LD1A/s12345
  ?AQB=1
  &ndh=1
  &pf=1
  &pageName=PDP%3A%20Astro-3000
  &g=https%3A%2F%2Fexample.com%2Fproducts%2Fastro-3000
  &r=https%3A%2F%2Fexample.com%2F
  &cc=USD
  &events=event1%2Cevent2%3D12.50
  &c4=telescopes
  &v4=ASTRO-3000
  &v15=summer-sale-2025
  &products=%3BASTRO-3000%3B1%3B299.00
  &mid=12345678901234567890
  &AQE=1
ParamMeaning
AQB / AQEStart/end markers — useful when grepping logs
ndh"No double hit" flag
pageNames.pageName
gPage URL
rReferrer
ccCurrency code
eventsEvents list
c1–c75props 1–75
v1–v250eVars 1–250
h1–h5hier1–hier5
l1–l3list1–list3
midMarketing Cloud Visitor ID
pe / pev1 / pev2Link tracking type / URL / name (only on tl() hits)
aidLegacy Analytics ID (cookie-based, mostly retired)
tTimestamp + timezone offset

The lab page at labs/debugger.html includes a paste-a-URL decoder that breaks every parameter out with its variable name. Use it for the first dozen hits you debug.

4 · _satellite.setDebug(true)

The single most useful Launch command. Type it into the browser console:

_satellite.setDebug(true);
// Then reload the page

Launch now logs to the console:

  • Every rule that matched its event criteria
  • Every condition evaluated and its result
  • Every action fired
  • The full value of every data element as it was read

This turns a black-box Launch property into something readable. The setting persists in localStorage until you call _satellite.setDebug(false) or clear storage, so once turned on, every page you visit shows you the wiring.

4.1 — Other _satellite helpers

_satellite.getVar("Page Name")     // read a data element's current value
_satellite.track("custom-event")    // fire a Direct Call rule by ID
_satellite.logger.enabled = true    // enable logger without full debug spam
_satellite.buildInfo                // turnaroundTime, libraryName, environment

_satellite.getVar() is invaluable: it lets you ask Launch "what would %productSku% evaluate to right now?" without firing a rule. If it returns the wrong value, your data element definition is wrong — not the rule.

5 · Adobe Experience Platform Debugger

A browser extension Adobe maintains. Installs into Chrome, Firefox, Edge. What it gives you:

  • A panel listing every Adobe product detected on the page, with version numbers.
  • A "Network" tab inside the extension showing parsed AA / Target / AAM / Web SDK calls — already decoded, with eVar names rather than v1.
  • A "Launch" tab showing the property, environment, and library currently loaded.
  • An "Auditor" tab that runs a battery of best-practice checks (multiple s objects, missing IDs, slow loads).
  • The ability to swap environments — replace the production Launch library with staging on the fly, without changing the site code.

Install link is one search away. Pin it to the toolbar; use it daily. It will not catch every bug — the network panel remains the source of truth — but for ninety percent of "what variable is this?" questions, it is faster than reading the raw URL.

6 · Debugging the Web SDK

Web SDK debugging is similar but the surface is different:

// Enable verbose logging
alloy("configure", { debugEnabled: true, ... });
// Or at runtime
alloy("setDebug", { enabled: true });

The console then logs every sendEvent with its full XDM payload. The Experience Platform Debugger handles Web SDK natively in its Edge Network tab.

The most important thing to verify: the XDM payload validates against your schema. Edge silently drops invalid events; your data simply doesn't arrive, and there's no client-side error. Check the response from the interact call — if the XDM was invalid, the response body contains validation errors.

7 · The triage tree

When a stakeholder says "this number is wrong," walk this tree:

"The eVar4 report is missing values"
         │
         ├── Step 1: Does eVar4 appear on the hit?
         │         (Network panel; filter b/ss; check v4=)
         │         │
         │         ├── NO  → Bug is in implementation
         │         │         ├── Is the rule firing?           (_satellite.setDebug)
         │         │         ├── Is the data element resolving? (_satellite.getVar)
         │         │         └── Is the variable being set?    (read s.eVar4 in console)
         │         │
         │         └── YES → Bug is downstream
         │                   ├── Processing rule dropping it?  (Admin → Processing Rules)
         │                   ├── VISTA dropping it?            (Adobe ClientCare)
         │                   ├── Wrong report suite?           (Check rsid on hit URL)
         │                   └── Classification mis-mapping?   (Classifications report)
         │
         └── Step 2 (always): Reproduce. Always reproduce yourself.
                              "Works on my machine" applies to analytics too.

Walk the tree top to bottom every time. The discipline saves hours of speculation.

7.1 — Common false alarms

  • "The page view isn't firing" — it is, but on a different report suite. Check rsid in the URL.
  • "My eVar disappeared after one day" — expiration is set to Page View or Visit when you expected longer.
  • "Numbers off by 5%" — bot filtering, IP exclusion rule, or the Marketing Cloud Visitor ID service is failing for a subset of users.
  • "Numbers off by 50%" — you're looking at one variant in an A/B test, or one device class, or one date range. Re-check filters.

8 · Checkpoint

You should now be able to:

  • Open the network panel and find an AA hit in under five seconds.
  • Decode v4, c4, events, pe, products on a raw hit URL.
  • Turn on _satellite.setDebug(true) and read the resulting log.
  • Walk the triage tree top-to-bottom without skipping steps.

This module is short by design. Debugging is mostly muscle memory — every hour at the network panel pays for itself ten times.