Integration Guide
Add our lightweight tracker to your frontend and start capturing user behavior receipts for your Customer Success team.
Two lines of code. Zero config. Zero performance impact.
Setup
Add the Snippet
Add this to the <head>
of your website. The second line sets up a queue so you can call identify()
anywhere in your code without worrying about script load order.
<script>
window.witnesConfig = { projectKey: 'YOUR_PROJECT_KEY' };
window.Witnes = { _q: [], identify: function() { this._q.push(Array.from(arguments)); } };
</script>
<script src="https://cdn.witnes.io/w.min.js" async></script> Identification
Identifying Users
There are three ways to associate sessions with a user. Pick whichever fits your app.
Do not use personally identifiable information as the User ID or Org ID
Never pass emails, full names, phone numbers, company names, or domains. Use opaque
internal identifiers (e.g. database IDs or UUIDs) for both userId and orgId. If you
choose to send identifiable data, you are solely responsible for any privacy violations (GDPR, CCPA, etc.). See our Privacy Policy.
Authenticated user
Call window.Witnes.identify()
after login — anywhere in your code. The queue stub in the install snippet ensures this works regardless of script load order. For TypeScript, use (window as any).Witnes.identify().
Type-safe npm package coming soon
If you prefer typed imports over (window as any), we are shipping an official type-safe package next.
// JavaScript — user only
window.Witnes.identify("user_4821");
// JavaScript — with org (B2B SaaS)
window.Witnes.identify("user_4821", { orgId: "org_acme" });
// TypeScript (CDN snippet)
(window as any).Witnes?.identify?.("user_4821", { orgId: "org_acme" }); Guest Mode — anonymous visitors
For guest sessions, call identify(null, { guest: true })
explicitly.
// JavaScript
window.Witnes.identify(null, { guest: true });
// TypeScript (CDN snippet)
(window as any).Witnes?.identify?.(null, { guest: true }); Billing
How Billing Works
Witnes calculates usage based on Page loads.
Tracked Page Loads
LOAD
Triggered when a page is first opened.
SPA_NAV
Triggered when the URL changes (even without a full page reload).
Compatibility
Browser Coverage
We support all modern browsers. Some advanced metrics are subject to browser API availability.
| Feature | Chrome | Edge | Safari | Firefox |
|---|---|---|---|---|
| Session Tracking | Tested | Tested | Tested | Expected |
| LCP | Tested | Tested | Tested | Expected |
| CLS | Tested | Tested | Tested | Expected |
| FCP | Tested | Tested | Tested | Expected |
| Long Tasks | Tested | Tested | N/A | Expected |
| Resource Timing | Tested | Tested | Partial | Expected |
| Network Info | Tested | Tested | N/A | N/A |
| sendBeacon | Tested | Tested | Tested | Expected |
Tested Versions: Chrome 131, Edge 131, Safari 18.5
Expected: Firefox 133+ per MDN compatibility data
Safari: LCP support added in Safari 18.2 / macOS 15.2 (December 2024)
Timing-Allow-Origin
If first-party API calls appear as 0 B in the waterfall,
your API is not exposing Resource Timing transfer sizes to the browser.
Add Timing-Allow-Origin on API responses with your
web app origin.
Timing-Allow-Origin: https://customer.com
Example: app on https://customer.com calling
https://api.customer.com should return the header
above.
Under the Hood
Technical Details
Performance
- Zero Blocking —
Uses
asyncandsendBeacon. Never slows your page. - Lightweight — < 4KB gzipped.
Security & Privacy
- Project Key — Routes data to your specific dashboard.
- User ID — Must be a non-identifiable internal ID (database ID or UUID). Never send PII.
- Org ID — Same rule. Use your database's opaque org or account ID. Never pass a company name, domain, or any value that maps to a real-world identity.
Troubleshooting
Events not appearing?
- 1
Check that
projectKeymatches your dashboard exactly. - 2
Ensure
Witnes.identify()is being called with a non-null string. - 3
Open your browser console and verify that requests to
api.witnes.io/ingestare returning 202 Accepted. - 4
Enable debug mode to see detailed output in the browser console:
<script>
window.witnesConfig = {
projectKey: 'YOUR_PROJECT_KEY',
debug: true,
};
</script> Ad blockers
Some ad blockers or privacy extensions may block the tracking script from loading. Ask the user to temporarily disable their ad blocker and try again to rule this out.