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

AttributeRequiredDescription
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.

Don't self-host individual files. The CDN is the only supported delivery path — self-hosted copies will miss security and detection updates.

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.