Skip to content

The signed-in visitor

When a visitor is signed in to your site, you can attach their visit to their identifier in your system: all their page views and events in the visit carry it, including those from before sign-in, and their previous visits under the same cookie are linked to them. The views expose it as user_id and person.

In the site’s Settings, check Accept signed-in visitors. As long as it is disabled, a received identity is ignored — the event is kept, without the identity — and counted as “Identity refused” in the Verification tab.

The token is an HS256 JWT, signed by your server with the site secret (site Settings › Secret). The signature prevents a visitor from impersonating another: never sign it in the browser.

ClaimRequiredRole
subyesthe visitor’s identifier in your system, 200 characters at most: stored as is in user_id
expyesthe token’s expiry; an expired token is rejected

Prefer an opaque identifier (a customer number, a UUID) to an email address: sub is readable in the views, and therefore in eodia insights.

import { SignJWT } from 'jose'
const secret = new TextEncoder().encode(process.env.EODIA_SITE_SECRET)
export async function eodiaIdentity(customerId) {
return new SignJWT({})
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
.setSubject(String(customerId))
.setIssuedAt()
.setExpirationTime('12h')
.sign(secret)
}
<?php
// No library needed: an HS256 JWT can be signed in a few lines.
function eodia_identity(string $customerId, string $secret, int $ttl = 43200): string {
$b64 = fn (string $s) => rtrim(strtr(base64_encode($s), '+/', '-_'), '=');
$header = $b64(json_encode(['alg' => 'HS256', 'typ' => 'JWT']));
$payload = $b64(json_encode(['sub' => $customerId, 'iat' => time(), 'exp' => time() + $ttl]));
$signature = $b64(hash_hmac('sha256', "$header.$payload", $secret, true));
return "$header.$payload.$signature";
}
import os, time
import jwt # PyJWT
def eodia_identity(customer_id: str) -> str:
now = int(time.time())
return jwt.encode(
{"sub": str(customer_id), "iat": now, "exp": now + 12 * 3600},
os.environ["EODIA_SITE_SECRET"],
algorithm="HS256",
)

In the tag, if the page is rendered server-side:

<script defer src="https://stats.example.com/a.js"
data-site="s_arvordemo001"
data-identity="<?= htmlspecialchars($token) ?>"></script>

Or later, at sign-in, in a single-page application:

EodiaAnalytics.identify(token) // at sign-in
EodiaAnalytics.identify(null) // at sign-out

The views link identities together without rewriting anything in the raw data:

  • within the visit: user_id is the identity seen during the visit; all page views and all events of the visit carry it, including those from before sign-in;
  • from one visit to another: person is the identity when the visitor’s cookie has signed in at least once, including for its earlier visits; otherwise, the visitor identifier. This is the column to count for “unique people”;
  • a cookie seen under two identities (a shared device) keeps the most recent one for person, and the case is counted in the check figures of the Verification tab.

Without a measurement cookie, linking is limited to the day: the visitor hash changes every day.

  • Regenerate, in the site’s Settings, creates a new secret, shown only once. The old one remains accepted for 24 hours, giving you time to deploy the new one.
  • The secret is encrypted in the database (AES-256-GCM) with the instance key, SECRET_KEY.

Access and erasure requests from people identified in this way are handled from the site: see data subject rights.

eodia analytics is free software by Eodia.