Optional enrichment

ClickStream's core product is Signals: traffic lanes, bot and answer-engine classification, behavior scores, and site-side decisions. Optional enrichment is available on both packages for sites that are allowed to attach visitor details to a ClickStream ID after the visitor produces a matchable signal. There is no per-site enrichment fee. Explore includes 5 successfully enriched profiles per month; Pro includes 25 successful profiles per billing account each month, then charges $0.03 per additional successful, unique profile.

Privacy model up front. The normal Signals install does not require enrichment. When a site enables enrichment, raw PII is encrypted before storage and reveal is password-re-authenticated, rate-limited, and audit-logged. Email and phone matching signals are normalized and hashed before they are used for enrichment joins.

First-party identity signals

SignalSourceHashingPrimary use
hemtracker.identify(email)SHA-256 of lowercased, trimmed emailInternal primary key
hemMd5sameMD5 of lowercased, trimmed emailPartner-compatible enrichment lookup format
hashedPhonetracker.identify({ phone })SHA-256 of E.164 normalized phoneSecondary primary key
customerIdtracker.identify({ customerId })Raw (not PII — your internal app id)Application/backend join
accountIdtracker.identify({ accountId })Raw account identifierAccount-level analysis
gclid / fbclid / msclkid / ttclid / twclid / sccid / epik / irclickid / dclid / li_fat_idURL query params on landingRawInbound click parameter capture
googleId / facebookId / linkedinId / appleIdSocial login callbackRaw (OAuth subject)Cross-device bridge via social login
maid + maidTypeMobile SDK bridgeRaw UUID (IDFA / GAID)Mobile-web unification
clickstreamId / referringClickstreamIdCross-site journey trackingRawBounded cross-site journey stitching

The first-party visitor cookie _cs_vid (legacy _cs_uid is still read as a fallback) is the anchor. Every identifier above hangs off that visitor id until tracker.identify() or a captured form signal connects it to a known profile.

The API you actually write

Identify

await tracker.identify('user@example.com');

Accepts a raw email. The SDK:

  1. Normalizes (lowercase, trim).
  2. Hashes (SHA-256 for internal use, MD5 for optional enrichment compatibility).
  3. Sends the identify event to your first-party tracking domain.
  4. Encrypts raw email server-side when raw identity capture is enabled for the site, so reveal and enrichment eligibility can be audited.
  5. Persists _cs_hem / _cs_hem_md5 local-storage slots so subsequent sessions on the same browser re-emit the hashes without asking.

Raw email is never sent directly to an enrichment provider, never appears in public Signals responses, and is never shown in Einstein without the audited reveal flow.

Identify with additional signals

await tracker.identify({
  email: 'user@example.com',
  phone: '+14155551234',
  customerId: 'cust_abc123',
  accountId: 'acc_xyz789',
});

Phone is normalized to E.164 (+CCCC...) before hashing. If the input isn't parseable as E.164, the SDK emits a warning and skips the phone hash without blocking the rest of the identify call.

Revoke identity

// Revoke the marketing category (identity storage):
await tracker.setConsent({ marketing: false });

// Or revoke every category except necessary:
await tracker.rejectAllConsent();

Revoking the marketing consent category clears every identity slot from local storage, cookies, and in-memory state, and emits a _consent_transition event for the audit trail. It also revokes thirdParty, which stops the optional enrichment pixel. Server-side person records are removed separately through the dashboard's visitor delete action — see Privacy under "Visitor rights — DSAR / export / deletion".

What ClickStream stitches

Given these signals arriving from different sessions, ClickStream links records using deterministic matchers such as hem, hashedPhone, and customerId. Every merge is auditable, and enrichment remains controlled by the site's plan, toggle, consent posture, and compliance profile.

Merge rules, in priority order:

  1. Exact hem match — same SHA-256 email hash across devices → same person record.
  2. Exact hashedPhone match — same SHA-256 phone hash → same person.
  3. Exact customerId match — same application id → same person.
  4. Social login bridge — same googleId / facebookId / linkedinId / appleId → same person.
  5. Fingerprint + IP household — same fingerprint_hash + same /24 IP subnet within a 48-hour window → same person, probabilistic confidence label.

Conflicts (same _cs_uid claiming two different hem values) generate a collision audit row and are NOT auto-merged. The dashboard surfaces collisions on the Identity Quality tab; operators resolve them manually.

Using the resolved identity

Via the Signals API

import { getVisitorOrNull } from '@clickstreamhq/signals';

const visitor = await getVisitorOrNull();
if (visitor?.identity.hasIdentifiedThisSession) {
  showLoggedInView();
}

The VisitorContext.identity block carries:

Full cross-session profile detail and enrichment reveal are available on both Free and Paid. Sensitive fields always require password re-authentication and an audit record; Free is limited to its bounded monthly sample.

Via the dashboard

People shows every resolved visitor with their sessions, Signals labels, and journey map. Optional enrichment surfaces on both packages only when the site has enabled it, the required consent exists, and ClickStream has a permitted match.

Identity enrichment

ClickStream can enrich identified visitors through DataShopper (DataMoon) when a site has enrichment enabled and the visitor produces a matchable signal. The monthly profile allowance is pooled across the billing account's enabled sites. It counts successful, first-delivered unique profiles—not vendor lookup attempts—and is separate from the package's monthly pageview allowance. Pro's 25,000 human pageviews do not mean 25,000 included enriched profiles. Email hashes are stored in Analytics Engine and the enriched profile store, joined via per-tenant HMAC, and used only under the site's consent and compliance profile.

The hem (SHA-256) hash is the durable first-party identity key. The hemMd5 hash is retained for the approved enrichment workflow. Raw email and phone values are encrypted before storage, are never shown by default, and require an audited reveal action.

Enrichment remains scoped to the site and plan controls configured in Einstein. If enrichment is disabled for a site, ClickStream still records first-party identity signals, but it does not request or attach enrichment data.

Enrichment is limited to the site's allowed regions, the US by default: the browser pixel loads only when the visitor's country is known and allowed, and server-side lookups skip a visitor whose known country is not allowed. An empty list allows every country, but never a visitor whose country is unknown. In the browser, the enrichment pixel also waits for Accept on the site's cookie banner, if the site shows one; with no banner, visitors are treated as consenting. Deciding whether a banner is needed, and providing one, is the site owner's responsibility. See Cookie banners on Privacy & compliance.

Retention

See also