Skip to content

@rabolic/web

Browser analytics in a few lines, under 8 KB gzip.

Install from npm or paste a script tag. The web SDK sends a page view for every route of a single-page app, measures how long each page was read, keeps the campaign that brought the visitor, and waits for consent when you ask it to.

  • No runtime dependencies
  • No CORS preflight
  • Calls never throw
import { rabolic } from '@rabolic/web'

rabolic.init({ projectKey: 'rb_pub_…', trackRoutes: true })

// after signup or login
rabolic.identify(user.id, { plan: 'pro' })

rabolic.track('signup_completed', { method: 'google' })

trackRoutes: true

A page view for every route, with no router plugin.

The SDK listens to the browser’s history, so React, Vue, Svelte and plain sites all get a $pageview per route. When a visitor leaves a page, $page_leave records how long they were active on it and how far they scrolled.

  • $pageview on load and on pushState, replaceState and popstate
  • Same-URL and hash-only changes are ignored
  • $page_leave with active_ms and scroll_depth (0–1)
  • On page hide, the queue goes out with sendBeacon

context.campaign

Every event knows where the visit came from.

The landing URL’s campaign parameters and click id are kept for the whole visit, and a landing with different ones starts a new session. Sessions are shared by your tabs and end after 30 minutes without an event, or the timeout you set for the project.

Requests go out as text/plain with the key in the body and no credentials, so the browser sends no CORS preflight.

What every web event carries
FieldWhat it holds
platformweb
pageURL, path, title and referrer
campaignutm_source, utm_medium, utm_campaign, utm_content, utm_term, and the click id type: gclid, fbclid, ttclid or msclkid
locale, timezoneFrom the browser, such as en-US and Europe/Berlin
screenWidth, height and pixel density
user_agentRabolic reads the browser, OS and device from it

the api

The whole API fits on one screen.

Calls made before init are kept, up to 100, and replayed. No method throws into your page; pass debug: true to see why a call was dropped.

Web SDK methods
MethodDoes
init(options)Starts the SDK. Logs and does nothing for a missing, invalid or secret key
track(event, properties?)A custom event, in snake_case. Names starting with $ are reserved
page(properties?)A manual $pageview
identify(userId, traits?)Sets the user id on this and later events, and sends $identify with the traits
reset()On logout: a new anonymous id and session, no user id, no super properties
register(properties) / unregister(key)Super properties, sent with every later event. Event properties win
setConsent('granted' | 'pending' | 'denied')Changes consent at runtime. optIn() and optOut() are short for granted and denied
flush()Sends the queue now. Never rejects
getAnonymousId()The anonymous id, or null before init
appLink(url)Adds rb_aid to a store or deep link, so your app can link the visitor
app.ts
// A custom event, in snake_case
rabolic.track('checkout_completed', { plan: 'pro_yearly' })

// Super properties: sent with every later event
rabolic.register({ app_version: '2.4.0' })
rabolic.unregister('app_version')

// A manual $pageview
rabolic.page()

// Carry this visitor into your app (adds rb_aid)
const link = rabolic.appLink('https://apps.apple.com/app/id1234567890')

// Send the queue now; never rejects
await rabolic.flush()

rabolic.init(options)

Options.

Only the key is required. With the script tag, set data-key and, for a proxy, data-host.

Web SDK options
OptionDefaultNotes
projectKeyrequiredThe publishable key, rb_pub_…
hostRabolic’s ingesthttps://ingest.rabolic.com, or your first-party proxy
trackRoutestrue$pageview on single-page-app navigation
trackPageLeavetrue$page_leave with active time and scroll depth
persistence'localStorage''memory' is cookieless: ids last one page lifetime
cookieDomaincurrent hostSuch as .example.com, to share rb_aid across subdomains
consent'granted''pending' until your consent banner answers
flushAt20Send when this many events are queued (1–500)
flushIntervalMs5000Send at least this often
debugfalseLog every call, and why a call was dropped

consent: 'pending'

Wait for consent, or store nothing at all.

The SDK never reads form fields, the clipboard or location, and never fingerprints the browser. What it does store, and when, is up to you.

  • 'granted'

    Granted

    The default. Tracks, stores the ids and sends.

  • 'pending'

    Pending

    Writes no cookie and nothing to storage, and sends nothing. Events wait in memory until you call setConsent('granted').

  • 'denied'

    Denied

    Drops the queue and removes everything the SDK stored, the cookie included.

  • persistence: 'memory'

    Cookieless

    No cookie and nothing in localStorage, without a banner. Ids live in memory for one page lifetime, so each page load is a new visitor.

privacy.ts
// Cookieless: no cookie, nothing in localStorage.
// Ids last one page lifetime.
rabolic.init({ projectKey: 'rb_pub_…', persistence: 'memory' })

// Or wait for your consent banner:
// nothing is stored or sent until it answers.
rabolic.init({ projectKey: 'rb_pub_…', consent: 'pending' })
rabolic.setConsent('granted') // or 'denied'

What it stores

With the default persistence: 'localStorage' and consent granted. Cookieless mode and pending consent store none of it.

What the web SDK stores in the browser
WhereNameWhat
localStoragerb_aidThe anonymous id: a random UUID
Cookie, first-partyrb_aidThe same id. SameSite=Lax, Secure on https, one year. It restores the id if localStorage was cleared
localStoragerb_sessionThe session id and the time of the last event, shared by your tabs
localStoragerb_queueEvents not sent yet, up to 1,000
localStoragerb_uid, rb_super, rb_configThe user id after identify(), super properties, and the project’s session settings

web sdk faq

The web SDK, answered.

How big is the web SDK?

The script on cdn.rabolic.com is under 8 KB gzip, and its build fails if it grows past that. The package has no runtime dependencies.

Does it track single-page apps?

Yes. With trackRoutes on (the default), it sends a $pageview on every pushState, replaceState and popstate, and a $page_leave for the page before. Hash-only changes and navigation to the same URL are ignored.

Does it set cookies?

By default it keeps a random anonymous id in localStorage and mirrors it to a first-party rb_aid cookie for one year. With consent: 'pending' nothing is written until consent is granted, and with persistence: 'memory' (cookieless mode) nothing is ever written.

Do I need a consent banner?

That depends on the law where your visitors are, and on your own advice. The SDK supports both routes: consent: 'pending' waits for your banner, and cookieless mode stores nothing at all. rabolic.com itself uses cookieless mode and shows no banner.

What does the script tag loader do?

It defines a small window.rabolic stub that queues your calls, loads https://cdn.rabolic.com/v1/rabolic.js asynchronously, and replays the calls in order once it has loaded. Without the loader, a plain script tag with a data-key attribute starts the SDK on its own.

Can I pin a version of the script?

Yes. /v1/rabolic.js is the latest release, and every release is also published at /v1/<version>/rabolic.js, such as https://cdn.rabolic.com/v1/0.1.1/rabolic.js.

Which campaigns does it record?

The utm_source, utm_medium, utm_campaign, utm_content and utm_term parameters of the landing URL, and which click id it carried (gclid, fbclid, ttclid or msclkid). A landing with different campaign parameters starts a new session, so each campaign gets its own visit.

Can I use a secret key in the browser?

No. The web SDK refuses rb_live_ and rb_test_ keys and logs a warning to rotate the exposed key. Browsers use the publishable rb_pub_ key, which can only send events and can’t send revenue.

Add Rabolic to your site in a few lines.

Start a 3-day trial without a card. It begins with your first event, so you can set up the SDKs first.

  1. 1

    Create a project

    Sign up, name your project, and copy its publishable key.

  2. 2

    Add an SDK

    Web, React Native, Flutter or Node.js, or the HTTP API. Or run npx rabolic init.

  3. 3

    Watch the first event arrive

    It shows in live events within seconds, and your trial starts then.