Tracking Script
A single IIFE bundle that handles analytics, fingerprinting and security signals. Add it once per page; everything else is auto-wired.
Installation
Paste this snippet into your <head> or just before </body>:
<script
data-sokol-site="YOUR_SITE_ID"
src="https://sokol-static.my-k.cloud/v1/sokol.iife.js"
async defer></script>
You'll find your Site ID on the site dashboard.
Script attributes
| Attribute | Required | Description |
|---|---|---|
data-sokol-site |
Yes | Site ID (UUID) issued by the console. |
src |
Yes | Must point to https://sokol-static.my-k.cloud/v1/sokol.iife.js or an equivalent transparent proxy path. |
async / defer |
Recommended | Avoids blocking page render. The script is safe to load asynchronously. |
What it collects
- Page view metadata — URL, referrer, language, viewport.
- Consent-gated interaction events — clicks, form submits, input/change, focus/blur, and scroll depth.
- After analytics consent, a device fingerprint used for bot/abuse detection (see below).
- Security integrity signals — automation hints and interaction timing/count summaries, without typed values.
- Adblock and anti-fraud heuristics.
- A persistent anonymous tracking cookie when analytics is allowed (see the Privacy Policy).
Device fingerprint
The fingerprint is computed by Sokol's own in-browser module; it does not load or contact any
third-party fingerprinting service. It runs only after analytics consent, in idle time, once per
page load, and yields between probes so it never blocks rendering. It never calls an API that
can show a permission prompt (camera, microphone, location, notifications, clipboard, storage
persistence, device pickers), and it does not read canvas pixels in Firefox with
resistFingerprinting, where that would raise a prompt.
Each characteristic (math precision, platform, locale, hardware, media preferences, screen,
storage support, plugins, GPU parameters, WebGL and 2D canvas rendering, installed fonts,
audio processing) is hashed separately. The ingest payload carries the per-component hash vector
next to the combined device hash, and the server recomputes the combined hash from the vector,
so a mismatching claim is flagged. Components a browser randomises (Brave farbling, Firefox
fingerprinting protection, Safari advanced fingerprinting protection) are detected with
known-answer checks and left out of the hash; the payload reports them as
excluded together with a confidence score. Signals that are useful
for matching but change too often (desktop screen size, canvas text rendering — which follows
the device pixel ratio and page zoom —, font preferences, WebGL extensions, color scheme,
permission states, keyboard layout, voices, adblock lists) are sent as auxiliary
hashes and are never part of the device hash. Further auxiliary candidates that privacy browsers
do not randomize (codec and hardware-decode support, WebGL2/WebGPU limits, emoji glyph metrics,
system UI fonts and colors, text layout, User-Agent Client Hints, and which protections are
active) let Sokol measure, per browser family and only in aggregate, which characteristics are
stable and distinctive before any of them is used in the hash.
The page visitor's Global Privacy Control and Do Not Track preferences are never used as fingerprint inputs.
Network data is not part of the device hash. The script fetches
/api/v1/enrich/<site>/investigate from the configured API base at most once
per page load and sends that snapshot alongside the fingerprint; the server compares it with
the ingestion request for risk scoring.
Event tracking
After analytics consent is granted, Sokol automatically captures common interaction
events. It never records input values. Elements can opt out with
data-sokol-ignore.
Use Sokol attributes for custom names and small properties:
<button
data-sokol-event="Signup CTA"
data-sokol-category="conversion"
data-sokol-label="Hero"
data-sokol-prop-plan="pro">
Start now
</button>
Umami-style declarative events are also recognized:
<button
data-umami-event="Signup CTA"
data-umami-event-plan="pro">
Start now
</button>
Plausible class-based tagged events are recognized too:
<button class="btn plausible-event-name=Signup+CTA plausible-event-plan=pro">
Start now
</button>
If Google Analytics, Google Tag Manager, Plausible, or Umami are present, Sokol mirrors their configured events into Sokol analytics. When analytics consent is denied, Sokol blocks those third-party event calls while still allowing consent-management calls.
Manual events can be sent with:
window.Sokol.track('Signup CTA', { plan: 'pro' }, { category: 'conversion' });
Consent manager
Consent management is configured per site in the console. When enabled, the main
script first fetches a small consent bootstrap config and lazy-loads
consent.iife.js. Analytics, fingerprinting, ingest, and SPA page-view
events wait until the visitor grants analytics consent. Sokol security features
remain necessary and continue to run.
Public consent configuration is loaded from
https://sokol-data.my-k.cloud first and falls back to the Sokol API.
A slow or unavailable evidence write never blocks the host page: the browser keeps
the choice pending and optional processing remains disabled until a valid proof is returned.
The consent API is exposed at window.Sokol.consent. It supports
hasConsent(category), hasFeature(featureKey),
openPreferences(), waitFor(key), and
runWhenAllowed(key, callback). The script also emits
sokol:consent-ready and sokol:consent-change events.
Google Consent Mode
If Google Consent Mode is enabled in the console, Sokol updates an existing
gtag or dataLayer when consent state changes. It does not
create a Google tag stub. If your Google tags load before Sokol, add a default-denied
snippet before those tags:
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('consent', 'default', {
analytics_storage: 'denied',
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
functionality_storage: 'denied',
personalization_storage: 'denied',
security_storage: 'granted'
});
</script>
CDN & versioning
The bundle is served from a global CDN at
https://sokol-static.my-k.cloud/v1/sokol.iife.js. The /v1/
segment pins you to the current major version; breaking changes ship under a new
prefix so existing integrations are never silently affected.
Proxying the bundle
If your security policy requires serving everything from your own domain, you may
transparently proxy the CDN. The only requirement is that you proxy the
entire https://sokol-static.my-k.cloud/v1/* path — the
main bundle pulls additional sibling assets (workers, sub-modules, consent manager, future
components) at runtime, and they all live under the same prefix.
Example with nginx:
location /sokol/v1/ {
proxy_pass https://sokol-static.my-k.cloud/v1/;
proxy_set_header Host sokol-static.my-k.cloud;
proxy_ssl_server_name on;
}
Then load the bundle from your own origin:
<script
data-sokol-site="YOUR_SITE_ID"
src="https://your-domain.example/sokol/v1/sokol.iife.js"
async defer></script>
Proxying only sokol.iife.js on its own will break detection features
that lazy-load companion scripts.