The snippet, consent, and revenue.

This page is for whoever owns your site's code. Send them this link. It covers the tracking snippet, consent mode, running several domains, per-order revenue, identified traffic, and visitor properties.

01 / The snippet

One tag, self-contained.

The snippet below is the shape, with a placeholder where your site key goes, so don't paste it as-is. Evarist hands you the real one when you add your site at app.evarist.ai/start, and it stays available in the app under Settings.

<script>
window.evarist=window.evarist||function(){(window.evarist.q=window.evarist.q||[]).push(arguments)};
(function(){var s=document.createElement("script");s.src="https://app.evarist.ai/script.js";s.setAttribute("data-evarist","YOUR-SITE-KEY");(document.head||document.documentElement).appendChild(s);})();
</script>

Put it in the <head> of every page: directly in your templates, or as a custom-HTML tag in your tag manager (Google Tag Manager, etc.) fired on all pages. The snippet is deliberately self-injecting so tag managers can't strip its site key; paste it whole, don't convert it to a bare external script.

It weighs about 13 KB compressed, loads asynchronously after your page, never blocks rendering, and fails silently if it can't load, so your site is unaffected either way.

Is it working? Open Settings, Overview in the app. It says whether events are arriving and when the last one did.

Separately from this snippet, Evarist also fetches your pages server-side, to build the site model and to verify on-page tags. If your WAF or CDN needs an allowlist rule for that crawler, see the EvaristBot page.

03 / Several domains

One brand, several domains.

Run the same brand on several domains, your .com and .fr, or a separate checkout domain? Install the same snippet on every domain, then add the other domain in the app, under Settings, Domains. From then on a visitor who crosses between them is recognised as one person, and their journey reads as one journey.

The same panel lists a site's domains and removes one at any time.

04 / Revenue

Per-order revenue from your code.

When the revenue amount varies per order and your checkout is your own code, fire the conversion yourself:

evarist('goal', 'purchase', { value: 49.90 });

The value is in major units (49.90 = €49.90). This fires the same conversion event as a no-code goal and respects the same per-session dedup.

Two input rules: the goal name is lowercased, then must be 1 to 29 characters of letters, digits, _ or -, with no spaces (an invalid name is dropped with a console warning). And value must be a number, not a string: { value: 49.90 }, never { value: "49.90" }, because a string is ignored and the conversion fires without revenue.

For fixed-value outcomes (a signup worth €49), skip the code and ask Evarist to create the goal with a value instead: Track what matters.

05 / Product ids

Which product was viewed.

Evarist can see that someone opened a product page. Whether it can tell you which product depends on how your store is built.

On Shopify, the id is already collected. The native app's web pixel sends the product id with each product view, so the data is there with nothing to wire. Asking about individual products on top of it is still being finished, so if that is what you are after, tell us and we will let you know the moment it lands. See Evarist on Shopify.

On your own storefront code, not yet. The tracker's track call takes an event name and nothing else, so there is no supported way to attach a product id to a view today. If that is what you need, tell us: it is on our list, and knowing it is blocking you moves it up.

What it unlocks, once it is there: which products get looked at and abandoned, which convert on a first view, and where a product sits in a journey rather than only how much it sold.
06 / Identified traffic

Connect form emails to visits.

Optionally, Evarist can connect the email a visitor submits on one of your forms to their on-site behaviour, so "who asked for a demo this week, and what did they look at first?" becomes answerable. It's off by default, per site, and double-gated: it captures nothing until you switch it on and the visitor has consented.

Turn it on: ask us to switch it on for your site. It needs Evarist's own tracker on the page.

The consent gate. Captured emails are only sent after an explicit consent signal reaches the tracker. If you use consent mode, the evarist('consent', { analytics: true }) call you already wire is that signal; if you don't, wire that same one call from your cookie banner's accept path. On Shopify, switch on consent mode and the store's banner drives it automatically.

What gets captured. Emails submitted in Wisepops popups and embeds are picked up automatically. For any other form, call the tracker from your own submit handler:

evarist('identify', { email: 'visitor@example.com' });

From then on, ask about identified visitors in the app, or in your assistant. Capture can be switched off the same way you switched it on, any time. Because the tracker reads its config from an edge cache, Evarist warns you in the rare case the cache flush fails (pages already loaded could keep capturing for up to an hour).

07 / Visitor properties

Segment by facts you know.

Attach a fact you know about a visitor, such as is_employee, plan or est_important, so you can ask Evarist to segment or exclude by it. It's declared-only: the tracker only ever sends a property name you declared first, up to 20 per site.

Declare it: ask your assistant ("declare a property called is_employee"), or use the Properties panel in the app under Settings. Pick a type (boolean, string, or number) and where the value comes from: your own code, or source data_layer (a GTM dataLayer path).

Set it from your code. Call the tracker with the declared name and a matching value:

evarist('set', { is_employee: true });
evarist('set', { plan: 'gold', seats: 12 });

An undeclared name never leaves the browser: no error, it is silently dropped. A value that doesn't match the declared type (a string where a number was declared, say) is dropped the same way. String values are capped at 256 characters.

Or map it from your dataLayer. Declare the property with source data_layer and a dot-path (e.g. user.vip), and the tracker reads it directly, no extra call needed:

window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ user: { vip: true } });
// declared with source "data_layer", path "user.vip" — the tracker picks it up
// from the existing dataLayer on load, and from every later push, automatically

Consent-gated, exactly like identified traffic: nothing ships before evarist('consent', { analytics: true }). A value set before consent is queued, not dropped: it sends on the first event after the visitor consents.

Property names that look like personal data (email, phone, …) are rejected at declare time, because properties are for segmentation, not identity; see identified traffic to capture an email instead.