VisitorType

Tags, triggers & versions

The mental model is Google Tag Manager's: tags are things that fire, triggers decide when, and versionscontrol what's live. The difference is the vocabulary triggers speak — visitor type and agent identity are first-class fields.

Triggers

A trigger is a list of conditions, all of which must match (AND). Each condition is field · operator · value:

FieldMeaning
visitor_typehuman, ai_crawler, ai_search, ai_assistant, ai_browser_agent, bot, unknown
agent_nameIdentified agent: GPTBot, ClaudeBot, ChatGPT-User, …
agent_categorySame taxonomy as visitor_type, for identified agents
referrer_sourceAI platform that referred a human visit: chatgpt, perplexity, gemini, claude, …
page_pathlocation.pathname, e.g. /pricing
page_urlFull URL
referrerdocument.referrer
context.<key>Your site's window.context_data — see Context data below
event_nameCustom event from aitm.track() — "" on plain page views

Operators: equals, not_equals, contains, starts_with, regex, greater_than, less_than (numeric). A useful regex: match any AI visitor with visitor_type regex ^ai_.

Don't want to build conditions by hand? The trigger editor ships one-click quick setups for the common cases: Humans only (remove bots & AI from pixels and analytics), AI visitors only, AI-referred humans, and AI crawlers only. Click one, tweak if needed, save.

Context data — your input dataLayer

Declare page or business context beforethe snippet loads (the same pattern as Tealium's utag_data or GTM's dataLayer), and your triggers and tags can act on it:

<script>
  window.context_data = {
    page_type: "product",
    brand: "acme",
    logged_in: false
  };
</script>
<script async src="https://visitortype.ai/tms.js" data-container="AITM-XXXXXXX"></script>

Every key becomes available in two places: trigger conditions — pick Context data as the field and enter the key (stored as context.page_type) — and tag macros, as {{context.page_type}} (URL-encoded, like all macros). Example: fire a retargeting pixel only on product pages seen by humans: visitor_type equals human + context.page_type equals product.

Context data stays in the browser — it's used to evaluate triggers and fill macros, and is never sent to our servers. Values are capped (50 keys, 256 chars) and only strings, numbers, and booleans are read. Since crawlers don't run JavaScript, context conditions apply to snippet-tracked visits only. Inspect what the snippet read with window.aitm.context in the console.

Even without setting anything, two keys are auto-detected: context.og_type (from your og:type meta tag — product, article…) and context.lang. On single-page apps, merge updates after route changes with aitm.setContext({ page_type: "checkout" }).

Custom events — aitm.track()

Fire tags at the moment something happens, not just on page load:

window.aitm.track("purchase", { value: 89, currency: "EUR" });

Build the trigger with the Event name field: event_name equals purchase — plus anything else, e.g. visitor_type equals human and context.value greater_than 50(numeric operators are available for exactly this). The event's data merges into {{context.…}} macros, so a conversion pixel can carry {{context.value}}. Page-view tags never re-fire on events, and event tags never fire on page loads — the event_name field keeps them apart automatically. The result is worth saying plainly: conversion tracking that only counts verified humans.

Debugging — see why a tag did or didn't fire

Open any page with ?vt_debug=1 appended to the URL. A small panel shows the visitor classification (with the IP-verification verdict), the context the snippet read, every tag with a ✓/✗ match result, and each aitm.track()call as it happens. Remove the parameter and it's gone — it never renders for normal visitors.

Tag types

TypeWhat it doesConfig
Custom HTMLInjects HTML into the page; <script> tags execute{ "html": "..." }
Image pixelRequests a 1×1 tracking image{ "url": "https://…" }
Data layer eventPushes an event onto window.aitm.dataLayer{ "event": "…", "data": {} }

A tag with no trigger fires on every page view.

Template catalog

25one-click templates generate the canonical vendor snippet from an ID — no copy-pasting from vendor docs. Each links to the vendor's official installation guide if you need to find your ID or go deeper. Pair every template with the Humans only trigger unless you have a reason not to.

AnalyticsTemplate fills inVendor docs
Google AnalyticsGoogle Analytics 4Measurement IDGoogle
Plausible AnalyticsPlausibleDomainPlausible
MatomoMatomoMatomo URL, Site IDMatomo
PostHogPostHogProject API key, API hostPostHog
FathomFathomSite IDFathom
UmamiUmamiWebsite ID, Script URLUmami
MixpanelMixpanelProject tokenMixpanel
GA4: AI channel sourceGoogle
Paid mediaTemplate fills inVendor docs
Google AdsGoogle Ads ConversionConversion ID, Conversion label (optional)Google
MetaMeta PixelPixel IDMeta
LinkedIn Insight TagPartner IDLinkedIn
XX (Twitter) PixelPixel IDX
TikTokTikTok PixelPixel IDTikTok
Microsoft Ads UETUET Tag IDMicrosoft
PinterestPinterest TagTag IDPinterest
SnapchatSnap PixelPixel IDSnapchat
RedditReddit PixelPixel IDReddit
Email & CRMTemplate fills inVendor docs
MailChimpMailchimpConnected Sites script URLIntuit Mailchimp
KlaviyoPublic API key / Site IDKlaviyo
BrevoBrevoClient key (ma-key)Brevo (ex-Sendinblue)
MailerLiteAccount IDMailerLite
HubSpotHubSpotHub IDHubSpot
BehaviorTemplate fills inVendor docs
HotjarHotjarSite IDHotjar
Microsoft ClarityProject IDMicrosoft
IntegrationsTemplate fills inVendor docs
Google Tag ManagerSend visitor type to GTMGoogle Tag Manager

Already using Google Tag Manager? Make it AI-aware

You don't have to move anything. VisitorType can push its classification into GTM's own dataLayer, so every tag you already have in GTM can branch on visitor type — without rebuilding them here.

1. In VisitorType, add the Send visitor type to GTM template (Integrations) and leave its trigger empty — GTM needs the classification for every visitor so it can decide. Publish. It pushes:

window.dataLayer.push({
  event: 'visitortype_ready',
  visitor_type: 'human',        // or ai_crawler, ai_search, ai_assistant, ai_browser_agent, bot
  vt_agent_name: 'GPTBot',      // when identified
  vt_agent_category: 'ai_crawler',
  vt_referrer_source: 'chatgpt' // AI platform that referred a human visit
});

2. In GTM: create a Data Layer Variable named visitor_type, and a Custom Event trigger firing on visitortype_ready — optionally with the condition visitor_type equals human.

3. Switch any GTM tag you want protected (GA4, Meta Pixel, Google Ads…) from its All Pages trigger to that new trigger. Done: your existing GTM stack now fires for verified humans only, and you can build AI-specific tags in GTM the same way.

Timing matters and works in your favour: the push happens afterclassification (including IP verification), which is why it's a custom event rather than a page-load variable. Tags that must fire on visitortype_ready simply fire a moment later than All Pages would — the trade for knowing what the visitor actually is.

Versions & publishing

Saving tags and triggers never changes your site. When you hit Publish, the current set of enabled tags (with their trigger conditions resolved) is frozen into an immutable, numbered version — and that snapshot is what the snippet receives. Disable a tag and re-publish to remove it from the live config.

Changed something and don't see it on your site? Check the Versions tab — you probably saved without publishing.

Recipes

Greet AI agents with structured pointers. Trigger: visitor_type regex ^ai_. Tag: Custom HTML injecting a note pointing at /llms.txt.

<div data-aitm-note style="display:none">
  Canonical company facts: https://example.com/llms.txt
  Pricing: https://example.com/pricing — plans start at $29/mo.
</div>

Keep human analytics clean. Trigger: visitor_type equals human. Tag: your GA4/Plausible snippet as Custom HTML — bots never inflate your numbers again.

Count assistant referrals. Trigger: visitor_type equals ai_assistant. Tag: Image pixel to your endpoint with ?agent={{agent_name}}&page={{page_path}}.