One tag on every page, high in the head. Nothing to configure after it: no events to name, no goals to define. This page is the whole integration: the tag, plus the two calls it exposes.
Your key is on the Setup screen in the app, shown once when it's issued. Paste the tag high
in the <head> on every page. Capture starts immediately, and the first
profiles fill within a couple of hours.
The key ships in your HTML, so treat it as public; it's built for that. All it can do is post visitor activity into your workspace; it can never read anything back. Browser posts are checked against your site's origin once it's set in the app (a best-effort abuse check, never an authentication boundary), and the key is stored hashed on our side.
Want a fresh one? Rotate it from Setup in one click. The old key is refused everywhere within a few minutes, and that includes the copy still sitting in your deployed HTML: paste the new key into the tag and redeploy right after rotating, or capture stops until you do.
A masked replay of each visit, plus a stream of plain events read from the markup your site
already publishes. Masking happens in the browser: every input value and every piece of rendered
text is replaced before anything is sent, with one narrow stylesheet edge described on the
privacy page. An iframe's contents are never recorded, and an
element you mark with data-cg-block keeps only an empty placeholder in the
replay. The full stance is on the privacy page.
The events:
pageview page_title page_leave tab_visible
Interaction
click rage_click exit_intent form_abandon site_search
Commerce
product_view add_to_cart_click cart_state datalayer
Context
attribution device geo js_error
Identity
identify
One detail worth knowing: on a shop whose own cart endpoint doesn't answer, barua infers the cart from add-to-cart clicks and marks it as inferred, so downstream decisions know the difference.
| Attribute | What it does |
|---|---|
data-key | Required. Your workspace key: pk_ followed by 48 hex characters. |
data-consent | Set to "required" to capture nothing, and write nothing to the device, until your consent banner calls barua.consent(true). A refusal stores only the refusal marker. The mode for an EU posture. |
data-auto-identify | Set to "off" to turn off automatic email pickup. Explicit barua.identify() calls still work. |
data-endpoint | Overrides where event batches post, for proxying through your own domain. The handed-out snippet doesn't need it, and the once-per-session city lookup still calls barua.ai directly. |
data-cg-block | This one goes on any element of your page. Its contents are never recorded; the replay keeps an empty placeholder carrying the element's tag, class, width, and height. |
The tag exposes window.barua with two calls.
Usually you never call it: when a visitor gives your site their email through a popup or a checkout, barua picks it up. For a logged-in app, call it once at sign-in so accounts are named too:
The sign-in event itself lands after the async tag has loaded in practice. A call that can
run at page boot instead (a restored session) gets the same guard as consent:
window.barua?.identify(…), repeated when your session state settles. On a
consent-required site, an identify fired before the visitor opts in is held in memory and
delivered when barua.consent(true) arrives.
traits carries what no form captured, an OAuth signup's name for instance.
Recognized keys: first_name, last_name, name,
phone. Values are capped at 80 characters, and any other key is dropped.
externalId is your own user id, and barua holds it as a claim rather than
trusting it: a browser can claim to be anyone. To make ids stick, assert them from your
backend through a bearer-authed endpoint; write
hello@barua.ai and we'll set you up.
For sites running data-consent="required". Wire it to your consent banner:
barua.consent(true) starts capture, and barua.consent(false) stops the
recorder, clearing both the queue and the pixel's stored values; the only thing a refusal
keeps is the refusal marker itself. Calling it repeatedly is safe.
The pixel loads async, so a banner that can fire before it's ready should guard the call
(window.barua?.consent(true)) and repeat it on the consent tool's change event.
Once a choice is stored, later pages need no call at all: the pixel reads it itself on
load.
Nothing extra to do. The pixel follows pushState and popstate
navigations, and corrects the page title after your router settles. Call
identify at sign-in and you're done.
Onboarding is a conversation today. Write hello@barua.ai, and a person answers.