Skip to content
Browse documentation

Template linter, simulator and tester

Check a tracking template before Google does — every linter code, the lint API, the Google Ads simulator with Google's Test statuses, and the transparency tester's checks.

Last updated 9 min read

On this page

TrackCrown has three tools that catch template problems before Google disapproves an ad:

ToolWhereWhat it does
Linterlive in the template builder, the simulator and the tester; POST /api/v1/google-ads/lintStatic check of the template text — no request is made.
SimulatorGoogle Ads → SimulatorBuilds the URL Google requests at click time and follows the chain like Google's Test button, in parallel and sequential mode.
Transparency testerGoogle Ads → Transparency testerRequests one link without following redirects and checks it against Google's transparent-tracker rules.

Linter codes#

Errors make Google disapprove the template or break the redirect; warnings work but should be fixed; notes are informational.

CodeSeverityMeaning
emptyerrorThe template is empty.
length_over_2048errorLonger than 2,048 characters (Google Ads and Microsoft limit).
space_or_control_charerrorSpaces, tabs, line breaks or control characters. Encode spaces in static values as %20.
stray_braceerrorAn unbalanced { or } outside a tag.
unknown_tagerror (Microsoft: warning)A tag the platform does not support, e.g. {gbraid}, or an invalid custom parameter (an underscore and 1–16 letters or digits).
ignore_in_templateerror{ignore} belongs in the final URL, not the template.
not_a_click_trackernoteThe template starts with {lpurl}: the click goes straight to the final URL and the tracker is never called.
non_httpserrorNot an https:// URL, or no hostname.
templated_hosterrorThe host contains a tag; Google must see a fixed hostname.
ip_hosterrorThe host is an IP address.
unknown_hosterrorThe host is not one of your active tracking domains.
host_not_certifiederror (warning with the pre-28-Aug-2023 option)Google Ads only: the domain is not certified.
non_click_patherrorA pixel, postback or SDK path (/i/, /px, /px.js, /px.gif, /pb, /postback, /conversion, /lp, /sdk.js).
unexpected_pathwarningNot /c/, /r/, /s/ or /click.
missing_lpurlerrorNo {lpurl}: Google cannot insert the landing page.
lpurl_not_in_url_paramerror{lpurl} is not the value of url=, or url= does not start with it.
static_url_paramerrorurl= carries a fixed address instead of {lpurl}.
duplicate_url_paramerrorurl= appears more than once (the tracker answers 403).
text_joined_to_lpurlerrorText glued to {lpurl}; only ?, &, # or the end may follow it.
lpurl_not_lastwarning (error for {unescapedlpurl})url= is not the last parameter. An unescaped landing page swallows every parameter after it.
force_transparent_after_urlwarningforce_transparent must come immediately before url=.
fragment_in_trackerwarningA # in the tracker URL: what follows is never sent.
duplicate_paramwarningA parameter appears twice; only the first value is recorded.
missing_gclidwarningGoogle Ads: no gclid={gclid}; conversions cannot be matched and offline uploads stay empty.
missing_msclkidwarningMicrosoft: no msclkid={msclkid}.
too_many_custom_paramswarningThe template uses more than 8 different custom parameters ({_name}). Google Ads and Microsoft Advertising hold at most 8 per campaign, ad group, ad or keyword: the others can only come from another level, and a custom parameter no level sets is inserted empty. (Microsoft ad extensions allow 3; exceeding that is an error.)
final_url_invaliderrorThe final URL is not a full http(s):// address.
final_url_has_lpurlerror{lpurl} in the final URL.
final_url_on_tracker_domainerrorThe final URL points at a tracking domain (any brand's) or localhost.
final_url_not_httpswarningThe final URL uses http://.
final_url_has_fragmentwarningUse page?{ignore}tc=1#anchor and url={unescapedlpurl}.

Final URL suffix codes (suffix_leading_separator, suffix_has_lpurl, suffix_has_ignore, suffix_has_url_param, and too_many_custom_params for suffixes) are listed in Final URL suffix + SDK.

Lint through the API#

POST https://app.trackcrown.com/api/v1/google-ads/lint — staff API keys (admin or analyst). Send a template, a suffix or both:

FieldTypeNotes
templatestring, ≤ 8,192The tracking template.
final_urlstring, ≤ 4,096Optional: also check the ad's final URL.
suffixstring, ≤ 4,096Optional Final URL suffix.
platformgoogle | microsoftDefault google.
allow_uncertifiedbooleantrue when the account used this tracker before 28 Aug 2023.

Example, where trk.example.com is one of the workspace's certified tracking domains:

Shell
curl -X POST https://app.trackcrown.com/api/v1/google-ads/lint \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"template":"https://trk.example.com/c/demo?gclid={gclid}&gbraid={gbraid}&url={lpurl}","final_url":"https://shop.example.com/"}'
JSON
{
  "data": {
    "ok": false,
    "template": {
      "ok": false,
      "host": "trk.example.com",
      "length": 72,
      "tags": ["gclid", "gbraid", "lpurl"],
      "issues": [
        { "code": "unknown_tag", "severity": "error",
          "message": "{gbraid} is not a ValueTrack parameter. Google appends gbraid to the landing page by auto-tagging; the tracker reads it from url=.",
          "hint": "Remove gbraid={gbraid}." }
      ]
    },
    "suffix": []
  }
}

ok is false when any error is present. Sending neither template nor suffix returns 400 invalid_request. The host checks use the key's workspace: its active tracking domains and their certification status.

Simulator#

Google Ads → Simulator reproduces what Google requests when the ad is clicked.

Inputs#

FieldNotes
Tracking template (account level)Required unless a lower level has one.
Lower-level templates (override the account template)Campaign, Ad group, Ad, Keyword. Empty = inherit.
Final URLRequired.
Mobile final URL (optional)Used when Device is Mobile.
Final URL suffix (optional)Appended before any #fragment.
{lpurl} escapingGoogle documented (? = & #) or Fully encoded.
DeviceMobile or Desktop (default Mobile).
NetworkSearch or Display (drives {ifsearch} / {ifcontent}).
Custom parametersUp to 8 _name = value pairs (more are refused, like Google Ads).
Sample ValueTrack valuesOn by default: fills realistic click-time values (below). Off: every ValueTrack tag is inserted empty.
Parallel, SequentialThe modes to run (both by default).
Account used this tracker before 28 Aug 2023Turns host_not_certified into a warning.

Click Simulate. With Sample ValueTrack values on, ValueTrack tags get realistic sample values like Google inserts at click time: a fresh test gclid per run (starting TeSt0gclid0Sim), campaign, ad group, ad, keyword and match type, and {network} / {device} codes matching the Network and Device you chose — so the tracker records the test click with a gclid, like a real one. Switch it off to insert every tag empty. You can run 20 simulations per minute.

How the URL is built#

  1. Final URL (the mobile one on mobile, when set).
  2. Final URL suffix appended before any #fragment.
  3. Custom parameters, then ValueTrack, substituted in the landing page; {ignore} removed.
  4. The most specific tracking template wins: Keyword › Ad › Ad group › Campaign › Account.
  5. Custom parameters, then ValueTrack, then the {lpurl} family substituted in the template. In parallel mode {lpurl} is https://www.google.com/asnc/<random id>.

How Google built this URL shows every step. The chain is then followed with server-side redirects only (no JavaScript), HTTPS only, at most 10 hops and 5 seconds per request.

Statuses#

StatusResultMeaning
Page foundpassSequential: the chain reached the final URL.
Chain reaches google.com/asncpassParallel: the tracker redirected to Google's endpoint.
Tracking chain terminatesfailA hop answered 4xx (a 403 means the destination is not allowlisted) or a 3xx without Location.
JavaScript redirect in tracking chainfailA 200 page redirects with JavaScript or meta refresh.
Final URL mismatchfailThe chain ended somewhere else than the final URL (or the asnc address).
UnreachablefailNo answer within 5 s, DNS or TLS failure.
Page not foundfailThe landing page answered 4xx/5xx.
Not HTTPSfailA hop is plain HTTP.
Too many redirectsfailStill redirecting after 10 requests.
HTTP redirect in tracking chainnoteHow many server-side redirects the chain used.
Landing page has additional parameterswarningParameters not in the final URL were added. Only the tracker's click ID may be.
Slow tracking chainwarningThe chain took more than 1 second in total.

Transparency tester#

Google Ads → Transparency tester requests a URL from TrackCrown's servers without following redirects.

  1. Paste a URL or template into Tracking URL or tracking template, or pick one under Use a generated link (a workspace template per tracking domain and one per active offer).
  2. For templates containing {lpurl}, enter the Expected final URL (required); it replaces {lpurl}. Enter https://www.google.com/asnc/TEST to test the parallel-tracking background call.
  3. Optional: Also follow the full chain (max 10 hops) and the User agent (Tester (bot) or Mobile Chrome).
  4. Click Run test.

The verdict reads PASS — this link behaves like a certified transparent tracker or FAIL — Google would not accept this link as transparent. Checks:

CheckFails or warns when
Visible next-hop parameter (url=)No usable url=.
HTTPS tracking URLPlain HTTP (allowed only for local development trackers).
Responds with one redirectNo redirect, a 403 (destination not allowed), a page instead of a redirect.
Redirects exactly to the url= valueLocation differs from the decoded url=.
Only non-foreign parameters addedAnything other than the click ID was added, removed or changed.
url= carries the expected final URLThe decoded url= differs from the expected final URL.
No cookie requiredThe redirect sets cookies.
Redirect is not cachedNo Cache-Control: no-store (warning).
Redirect latencyMore than 1,000 ms to the first byte (warning).

With the full chain on, it also reports Chain reaches google.com/asnc, Second hop is the url= target, No uncertified intermediate trackers, redirect loops, chain length and whether the final page loads.

Google's Test button#

Google Test statusCauseFix
Page foundThe chain reached the final URL.—
Tracking chain terminatesThe tracker answered 403/4xx.Allow the landing-page host; check the link key exists.
JavaScript redirectA page in the chain redirects client-side.Only server-side 3xx redirects are allowed.
Final URL mismatchThe chain ends on another host or path.Check for a nested redirect, a wrong url=, or a static URL instead of {lpurl}.
UnreachableTimeout, DNS or TLS failure.Check the domain is active and its certificate valid.
Page not foundThe landing page returns 404/410/5xx.Fix the landing page.

More fixes: Google Ads test failures. Every refusal code the tracker can return is listed in Error and reason codes.

Something unclear or missing in this article?Tell us