Skip to main content
InstantCampaign can measure visits to your own website and your hosted landing pages, attribute them to channels and campaigns, and connect them to known contacts. It does this without cookies.

Install tracking on your website

1

Create a tracking token

Go to Settings → Tracking tokens and click New Token. Give it a Label that identifies the site or environment, such as “Production website”. Use one token per website or environment.
2

Copy the snippet

The token is shown once. Copy it now. The dialog also shows the embed snippet:
3

Add it to every page

Paste the snippet into your site’s <head>, or into your site builder’s “custom code” setting. Single-page apps are handled: route changes count as pageviews.
4

Restrict it to your domains (recommended)

Back on Tracking Tokens, open Manage allowed domains for the token and add your site’s hostnames, such as example.com. Up to 20 domains per token. With no domains, all origins are allowed.
Hosted landing pages track themselves. There’s nothing to paste. To stop collecting on them, turn off Track landing pages under Settings → General.

The JavaScript API

The snippet also exposes ICTrack for custom tracking:
identify declares who the visitor is. Because the snippet runs in the visitor’s browser, that declaration only counts when you turn on Trust identity declared by your site code (below).

How a visitor becomes a known contact

A visit is anonymous until one of three things happens. Each of them links the visit, and that visitor’s other visits of the same day, to the contact.
  1. They arrive from one of your emails. When a campaign or journey links to a site listed in a tracking token’s Allowed Domains, InstantCampaign adds a signed visitor id to the link. A recipient who clicks through is recognized as that contact. Links to other domains are left untouched, so the id never reaches third parties. On by default; turn off Settings → Tracking tokens → Identify visitors who arrive from my emails to send plain links (see Privacy).
  2. They submit one of your forms. Any InstantCampaign form on the site identifies the visit: a popup or embedded form, a Form block on a hosted landing page, or the email step of a web push prompt. The address is captured by InstantCampaign’s own form endpoint, so this works without any setting, for new and existing contacts alike. Always on.
  3. Your site declares it. ICTrack.identify(email), or an event or goal sent with an email, identifies the visit when Settings → Tracking tokens → Trust identity declared by your site code is on. The email must belong to an existing contact; a declaration never creates one. This is how Salesforce Marketing Cloud Personalization treats identity declared by its sitemap. It is off by default because the tracking token is public: with it on, anyone who types another person’s email into a field your site passes to identify() can attach their visit to that contact and start that contact’s Website Event journeys.
With Persistent with consent on and the visitor’s consent, this also reaches back across days: their earlier visits and events are linked too (see Recognising returning visitors). When a visit becomes known, the events it recorded while anonymous are merged into the contact as history: they appear on the contact’s activity and count towards goal totals and segments, but they do not start journeys retroactively. Journeys start from events recorded after the visitor is known.

Privacy

Website measurement is first-party audience measurement that InstantCampaign runs for you as your processor. In the UK (the statistical-purposes exception) and in France (the CNIL audience-measurement exemption) that kind of measurement runs without a consent banner on conditions: your visitors are told what it is and who provides it, they can object easily, and visit-level data is kept only as long as needed and then aggregated. InstantCampaign gives you what each condition needs.
  • No cookies in the default Cookieless mode. A visitor is a server-side hash of your workspace, the IP address and the browser, which changes every day at midnight UTC. The raw IP address is never stored. A visitor id is stored only if you turn on Persistent with consent and the visitor agrees (see Recognising returning visitors).
  • Country comes from the browser’s time zone, not IP geolocation. That’s why there are no city-level reports.
  • Referrer query strings are dropped. Crawlers and bots are ignored.

Let visitors object

Put this link on your site, for example in your privacy policy or footer:
It stops the snippet in that browser: no more pageviews, time on page or events are sent from it, on any page of your site, until the visitor opts back in (ICTrack.optIn()). Settings → Tracking tokens shows the same link ready to copy. Hosted landing pages show their own line at the bottom when they measure visits: “This page measures visits anonymously. Opt out”, in the page’s language, followed by a Privacy policy link when you set a privacy policy URL (below).

Tell visitors in your privacy policy

Settings → Tracking tokens → Privacy policy text gives you a ready-to-paste paragraph, written from your current settings: InstantCampaign as your processor, the purposes (anonymous measurement, and linking a visit to a contact when the visitor arrives from your email, submits your form, or, only if you turned it on, is declared by your site code), the daily-changing hash with no cookie, how long visits are kept, and the opt-out link; while email links carry the visitor id it also says that in France such per-recipient links need the visitor’s consent. It’s an English template: adapt it to your policy and check it with your counsel. Settings → Tracking tokens → Visitor identity → Privacy policy URL is the address of your own privacy policy (it must start with https://). When it’s set, the consent banner and the footer line of your hosted landing pages link to it, and the paragraph above ends with “See our privacy policy at …”. Leave it empty for no link.

How long visits are kept

Visit-level records (visits, pageviews and anonymous events) are kept for 400 days (about 13 months). After that they’re reduced to daily totals per channel, source, device and country, and the individual records are deleted. Events that belong to a known contact stay on the contact. In the Website report, the totals for sessions, pageviews and time on page include those daily totals when the period reaches back that far (All time, or the comparison with a long period), and a line under the totals says how many sessions come from aggregate history. Visitors, bounce rate, identified visitors, the chart and every breakdown cover the visit-level records only, and so does any filter the daily totals don’t keep (browser, landing page, page, campaign tags and the like).

Global Privacy Control and Do Not Track

Browsers that send Global Privacy Control or Do Not Track are still counted, anonymously, but never linked to a person: the visit isn’t attributed to a contact (not even from an email link), ICTrack.identify() is ignored, and events are recorded without a contact, so they start no journeys. If such a visitor submits one of your forms, the contact is still created or updated, because they gave you their details, but the visit isn’t attached to it. InstantCampaign publishes /.well-known/gpc.json to say it honours GPC. When the browser sends GPC, your hosted landing pages also say so at the bottom of the page: “Your opt-out preference signal has been honored”, in the page’s language, as California’s rules require from 2026.

Identify visitors who arrive from my emails

Settings → Tracking tokens → Identify visitors who arrive from my emails decides whether links in your emails carry the signed visitor id. In France the CNIL’s 2026 recommendation on email tracking treats per-recipient tracking links as needing the recipient’s consent, so turn the switch off for French recipients unless you collected that consent. The campaign send wizard’s tracking step carries the same note. With the switch off, clicks are still counted, but a visit that starts from an email is no longer attributed to the contact.

What the scripts store in the browser

A/B tests store nothing: the variant a visitor sees is chosen on our server from the same daily hash, so a visitor keeps one variant for the day without any cookie. If your site has its own consent banner for other cookies, keep using it. The pages we host for you set no cookies unless you turn on Persistent with consent and the visitor accepts recognition. The snippet keeps a consent state for every page view with two purposes:
  • Measurement (analytics): the Website report. On by default, because it’s the exempt processor measurement described above. When your consent manager refuses it, the snippet sends nothing at all on that page.
  • Recognition (identity): linking the visit to a contact and, with Persistent with consent, recognising the visitor across visits. Never on by default. When it’s refused, the visit stays anonymous whatever happens: email links, ICTrack.identify() and form submissions still work, but the visit isn’t attached to the contact.
The snippet reads the state from, in this order: your own code (ICTrack.consent() or the tag’s data-ic-consent attribute), IAB TCF v2.2, Google Consent Mode v2, then a known consent manager (OneTrust, Cookiebot, Usercentrics, Didomi, CookieYes, Klaro, iubenda). Nothing is stored by the snippet: your consent manager re-issues the choice on every page, and the snippet follows every change. Global Privacy Control and Do Not Track always switch recognition off. Every decision is kept as a consent record, and when the visitor becomes a known contact their decisions are added to the contact’s consent history.

Settings

Settings → Tracking tokens → Visitor identity has these settings:
  • Mode: Cookieless (the default, nothing changes) or Persistent with consent: visitors who agree to recognition get a visitor id and are recognised across visits (below), hosted pages show the consent banner, and every consent decision is recorded.
  • Consent source: Auto-detect (read TCF, Consent Mode and the consent managers above), My site code (recognition waits until your page calls ICTrack.consent()), or InstantCampaign banner on hosted pages.
  • Forget anonymous visitors after (days): how long a visitor id lives on our side without a visit, 30 to 395 days, 90 by default. Visits already linked to a contact stay linked.
  • Require a marketing consent for identity: Auto (required while your workspace sends audiences to ad platforms), Always or Never. When required, recognition also needs the marketing category: TCF purposes 3 and 5, Consent Mode ad_user_data, OneTrust C0004, Cookiebot marketing, CookieYes advertisement, iubenda purpose 5.
  • Privacy policy URL: your privacy policy, linked from the consent banner and the footer of hosted landing pages (see Tell visitors in your privacy policy).
Choosing Persistent with consent opens a short confirmation first. It tells you what the mode stores and shows, needs your Privacy policy URL to be set, and asks you to confirm that your privacy policy covers it. Switching back to Cookieless needs no confirmation. The Privacy readiness card at the top of the page shows the result as a short status list: the mode, the privacy policy link, whether the banner will show on your hosted pages, how many of the last 7 days’ visits to your own website carried a consent decision and from which consent manager, how many visitors are recognised, and when the confirmation was given. A warning there names the one thing that stops recognition from working, for example “none seen on: blog.example.com” when your own site has no consent manager wired. A Cookieless workspace that changed nothing has no warnings.

Tell the snippet yourself

On the tag, data-ic-consent sets how the snippet decides:
With manual, the visit is measured anonymously and nothing is linked until you call ICTrack.consent({ identity: true }). With granted, consent managers are not read at all, but Global Privacy Control and Do Not Track still switch recognition off. Consent source: My site code in Settings has the same effect as manual on every tag that says nothing. Every consent manager works in one of two ways. Pick one. Blocked until consent. You mark the tag with your consent manager’s own attribute and type="text/plain" (or the type it asks for). The browser doesn’t run a text/plain script, so nothing at all is sent until the visitor agrees; then the consent manager turns it into a real script and the snippet starts as usual. The snippet finds its tag by data-site-id, so it doesn’t matter that the consent manager runs it late, and it reads its address from src, Klaro’s data-src or iubenda’s suppressedsrc. Once running, it still reads the consent manager, so a later refusal stops it and recognition follows the categories the visitor chose. Let InstantCampaign read your consent manager. You paste the plain tag:
With Consent source: Auto-detect (the default) no code is needed: the snippet recognises the consent manager on the page, waits up to a second for it to answer before the first hit, and follows every change the visitor makes. A consent manager that loads after the snippet is picked up when the page finishes loading. When it refuses measurement, nothing is sent from that page. Each recipe below is checked by our test suite against the snippet itself. OneTrust Blocked until consent: put the tag in the Performance category (C0002).
Let InstantCampaign read your consent manager: no code. The snippet reads OnetrustActiveGroups (C0002 for measurement, C0004 for the marketing consent) and follows OneTrustGroupsUpdated. Cookiebot Blocked until consent: the statistics category.
Let InstantCampaign read your consent manager: no code. The snippet reads Cookiebot.consent.statistics (and marketing) and follows CookiebotOnAccept, CookiebotOnDecline and CookiebotOnConsentReady. Usercentrics Blocked until consent: add a data processing service named “InstantCampaign” in the Usercentrics admin and block the tag behind it.
Let InstantCampaign read your consent manager: no code, as long as the service exists (named like InstantCampaign or Web analytics; a service of that name in the marketing category is the marketing consent). The snippet reads UC_UI.getServicesBaseInfo() and follows UC_UI_INITIALIZED and UC_UI_CMP_EVENT. If you set a custom window event in Usercentrics, name it on the tag: data-ic-uc-event="myUcEvent". Didomi Blocked until consent: add InstantCampaign as a custom vendor in the Didomi console and use the id Didomi gives it.
Let InstantCampaign read your consent manager: no code. The snippet waits for didomiOnReady, reads Didomi.getUserStatus() (measurement = measure_content_performance; recognition also needs cookies, and select_personalized_ads or create_ads_profile for the marketing consent) and follows consent.changed. CookieYes Blocked until consent: the analytics category.
Let InstantCampaign read your consent manager: no code. The snippet reads getCkyConsent().categories.analytics (and advertisement for the marketing consent) once the visitor has acted, and follows cookieyes_consent_update. Klaro Blocked until consent: a service named instantcampaign in your Klaro config; Klaro uses data-src for the address.
Let InstantCampaign read your consent manager: no code. The snippet reads klaro.getManager().consents.instantcampaign once the visitor confirmed, and watches the manager for changes. Rename the service on the tag with data-ic-klaro-service="web-stats"; add a service instantcampaign-marketing when a marketing consent is required. iubenda Blocked until consent: purpose 4 (measurement); iubenda uses suppressedsrc for the address.
Let InstantCampaign read your consent manager: no code. The snippet reads _iub.cs.api.getPreferences() and chains your _iub.csConfiguration.callback.onPreferenceExpressed (yours still runs): purpose 4 is measurement, purpose 5 the marketing consent. IAB TCF v2.2 (any TCF consent manager) Blocked until consent: not needed. Let InstantCampaign read your consent manager: no code. The snippet listens through __tcfapi("addEventListener") and acts on tcloaded and useractioncomplete: purpose 8 for measurement, purposes 1 and 8 for recognition (plus 3 and 5 when a marketing consent is required), from the publisher consents or the purpose consents. Outside the GDPR (gdprApplies: false) both are on. Google Consent Mode v2 Blocked until consent: not needed. Let InstantCampaign read your consent manager: no code. The snippet follows your gtag("consent", "default" | "update", …) calls (and dataLayer.push(["consent", "update", …])): analytics_storage decides measurement and recognition; ad_user_data is also needed for recognition when a marketing consent is required. A default limited to some regions is ignored. With Mode set to Persistent with consent, hosted landing pages (including your custom domain) show a small consent banner in your page’s theme and language, with two choices, Accept measurement and recognition and Only what is necessary, plus Manage. “Only what is necessary” keeps the anonymous measurement and refuses recognition. The banner stays hidden when the page has its own consent manager or your page code calls ICTrack.consent() within a second of loading, and it never shows with Consent source set to My site code or in the builder. When you set a privacy policy URL, the banner links to it. The choice is remembered in the visitor’s browser (ic_consent_choice) for your workspace only: on our shared host pages.instantcampaign.ai it applies to your pages and never to another workspace’s, and on your custom domain to the whole domain. A Consent choices link at the bottom of the page lets them change it. With Mode set to Cookieless the banner never shows.

Recognising returning visitors

With Mode set to Persistent with consent, a visitor who agrees to recognition (through your consent manager, your code or our banner) gets a visitor id: a random value created by our server, never chosen by the browser and never shared between workspaces. It’s kept in a first-party cookie called ic_uid (and a copy in the browser’s storage, in case the cookie is cleared). On hosted landing pages our server sets the cookie for your pages only.
  • What it does. The visitor’s visits are linked together. When they identify (from your email, a form, or your site code), all their earlier visits and anonymous events are added to the contact as history, not just today’s. Later visits are linked to the contact automatically.
  • How long it lasts. The cookie is set once for 13 months and isn’t extended on later visits. Browsers decide too: about 13 months on Chrome and Firefox, but 7 days without a visit on Safari and Brave. On our side, a visitor id that isn’t seen for the number of days you chose (90 by default) is forgotten; the visits stay in your report, anonymous.
  • Safeguards. If two visitor ids are linked to the same contact within 30 minutes (a shared computer, say), the second one isn’t merged. A visitor already linked to someone else is moved only when they submit a form or your site declares who they are, never by an email link alone. Every merge, skip and move is logged (with ids and counts only).
  • Withdrawing. When the visitor withdraws recognition (your consent manager, ICTrack.consent({ identity: false }), the Consent choices link on hosted pages, ICTrack.optOut(), or a Global Privacy Control / Do Not Track signal), the cookie and its copy are deleted and the visitor id is deleted on our side. What was already linked to the contact stays linked; withdrawal applies from then on. Erasing the contact removes their visitor ids, and they won’t be silently recognised again on their next visit.
  • In the report. Analytics → Website shows Identified across visits and a consent panel: how many visits granted recognition, refused it, carried a privacy signal or made no decision.

Website Traffic

Analytics → Website (the Overview tab) shows, for the selected period:
  • Visitors, Sessions, Pageviews, Time on page (time the page was actually visible) and Bounce rate, each compared with the previous period, plus how many visitors were Identified (known contacts).
  • Visitor identity and consent: visits Identified across visits (through the visitor id) and how many visits granted recognition, refused it, carried a privacy signal or made no decision.
  • Traffic over time, switchable Daily / Weekly / Monthly, with the same campaign and journey markers as the email charts.
  • Tabbed breakdown cards:
    • Top pages: Pages, Landing pages and Exits
    • Top sources: Referrers, Sources, Channels and Channel groups
    • Top campaigns: utm_campaign, Mediums, Contents and Terms
    • Devices: Devices, Browsers and OS
    • Countries: a Map or List view
  • Traffic by day and hour: a heatmap in your workspace timezone.
Click any row to filter the whole dashboard by it. Tick Identified visitors only to see only known contacts. Definitions. A session continues while there’s activity within 30 minutes. A bounce is a one-page session with less than 10 seconds of visible time.

Live

Analytics → Website → Live (the Live tab, or the “online now” badge) shows who’s on the site in the last 1, 5 or 30 minutes, refreshed every 10 seconds: current pages, where visitors came from, channels, campaigns, devices, countries, and an activity list of the most recently active visitors. Visitors are anonymous until they’re identified as a Known contact. On very busy sites, counts cover the most recent 1,000 sessions.

Explore

Analytics → Website → Explore (the Explore tab) is for custom reports. Pick a preset from All reports, or click Create my own and Group by up to 4 dimensions. The table shows sessions, visitors, pageviews, average engaged time and bounce rate. Use Having at least to hide rows with few sessions. The report lives in the URL, so copy the link to share it. Export CSV downloads the table.

Website Events

Analytics → Website → Events (the Events tab) lists custom events sent with ICTrack.event(): Event Name, Contact (or Anonymous), Properties, Source and Time. Filter by event name.

Channels and attribution

Each visit is assigned a channel: direct, search, social, email, paid, AI assistant or referral. The channel comes from UTM tags first, then ad click ids (such as gclid or fbclid), then the referrer. To change how visits are classified, see Attribution rules. To see which channels, sources and rules go on to earn goals, open Conversion attribution.

AI assistants

Visits from AI assistants get their own channel, AI assistants, with the assistant as the source: ChatGPT, Perplexity, Gemini, Microsoft Copilot, Claude, DeepSeek, Grok, Meta AI, Mistral Le Chat, Duck.ai, You.com and Poe. A visit counts when it arrives with the assistant’s referrer (for example chatgpt.com or perplexity.ai), with a utm_source naming it (ChatGPT adds utm_source=chatgpt.com to the links it cites), or with utm_medium set to ai, llm or ai-assistant on your own links. Many assistant apps send no referrer at all, so treat the count as a minimum: some of those visits show up as direct. When someone signs up through one of your forms or landing pages during such a visit, the contact is marked with that visit’s channel. To build an “agent-sourced” segment, add the rule Acquisition channel equals AI assistants (see Segments). The channel is recorded once, when the contact is created, and never changes afterwards; contacts added before this existed have no acquisition channel. If your workspace added starter attribution rules before AI assistants were covered, Add AI assistant rules on the Attribution rules page adds the missing ones. Then use Re-run over past visits to reclassify earlier visits.

Troubleshooting

Make sure the snippet is on the page and uses your full token. Check that the site’s hostname is in the token’s Allowed Domains, or that the list is empty. Also check that the testing browser hasn’t opted out (ICTrack.isOptedOut() in the console; ICTrack.optIn() undoes it).
Tokens are only shown once. Create a new token, update the snippet, then revoke the old one.
The link’s domain must be listed in a tracking token’s Allowed Domains, and Identify visitors who arrive from my emails must be on. A token with no allowed domains doesn’t add the id to any link. The tracking snippet must also be installed on the page the link opens. A browser with Global Privacy Control or Do Not Track on is never identified.
The visitor was not known when the event was recorded. Check the Contact column on the Events tab. A visitor becomes known by arriving from one of your emails, by submitting one of your forms, or, with Trust identity declared by your site code on, by your site calling ICTrack.identify() with an existing contact’s email. A journey only starts for events recorded after that point. A browser that sends Global Privacy Control or Do Not Track is measured anonymously and never identified, so test without them.