Docs
Install the script
One line in the <head> of every page. The visitor id, custom events and revenue attribution are a few lines more.
The script
Add a website in the app and copy its site id. Then put this line in the <head> of every page. It is under 2 KB, loads deferred, and sends each event with a beacon, so it never blocks rendering.
<script defer data-site="YOUR_SITE_ID" src="https://glai.io/glai.js"></script>- The first visit shows in the dashboard within seconds. Localhost is ignored unless you ask for it (below).
- Single-page apps are covered: every pushState and back/forward navigation is a pageview.
- Clicks on links to other sites are recorded as outbound events, with no extra code.
Where to paste it
Pick your platform. The line is the same everywhere; only the place changes.
Paste the line inside <head> of every page, or of the one layout file every page includes.
<head>
…
<script defer data-site="YOUR_SITE_ID" src="https://glai.io/glai.js"></script>
</head>Attributes
Two optional attributes on the script tag change how visitors are counted and where.
| Field | Type | Description |
|---|---|---|
| data-siterequired | string | The site id from the app (Sites → your site → Install). |
| data-privacy | "daily" | Strict mode: nothing is written to the visitor's browser. Visitors are counted with a hash that changes every day, so journeys across days and revenue attribution by visitor id are off. |
| data-dev | "true" | Record visits on localhost too. Off by default so your own development does not count. |
<script defer data-site="YOUR_SITE_ID" data-privacy="daily" data-dev="true" src="https://glai.io/glai.js"></script>Custom events and goals
Call glai(name, props) anywhere in your code, or tag an element with data-glai-event and the click is sent for you. Any event can be a goal in the app, which gives you its conversion rate by source. A value prop is counted as revenue for that event.
// Somewhere after the script tag; calls made before it loads are queued.
glai('signup')
glai('order', { value: 49, plan: 'growth' }) // value is counted as revenue for the event
glai('download', { file: 'pricing.pdf' })<button data-glai-event="pricing_cta" data-glai-prop-plan="growth">Start Growth</button>Event names: up to 60 characters. Props: up to 20 keys, each value up to 200 characters. Props are shown on the visitor's journey.
Identify a visitor
After someone signs in or signs up, tell the script who they are. Their journey then carries the name, and a payment that arrives with the same email is tied to them even when the checkout lost the visitor id. An identify call is not an event and does not count towards your plan.
glai('identify', { email: 'jane@example.com', name: 'Jane Doe', id: 'user_123' })Revenue attribution
Every payment is matched to the visit that brought it. Three steps: pass the visitor id into the checkout, point the provider's webhook at your site's address, and paste the signing secret in the app.
1 Read the visitor id
The script keeps a random id in the visitor's browser and in a first-party cookie called glai_vid, so your server can read it when it creates a checkout.
const visitorId = (document.cookie.match(/glai_vid=([a-z0-9]+)/) || [])[1] || ''
// Send it to your server with the checkout request, or read the cookie there.2 Pass it to the checkout
Always under the key glai_visitor_id. Pick your provider.
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: 'price_…', quantity: 1 }],
success_url: 'https://example.com/thanks',
metadata: { glai_visitor_id: visitorId }, // or client_reference_id: visitorId
subscription_data: { metadata: { glai_visitor_id: visitorId } }, // renewals carry it too
})3 Connect the webhook
Open the site's Revenue page in the app: it shows the webhook address for each provider. Add that address in the provider's dashboard (Stripe: Developers → Webhooks, events checkout.session.completed, invoice.paid and charge.refunded), then paste the signing secret the provider shows you into the Revenue page. Payments, renewals and refunds appear from then on, each next to the visit that brought it.
The secret is encrypted before it is stored and is used only to verify the provider's signature. Card details never reach Glai.
What counts as an event
| Sent by the script | Counted |
|---|---|
| Pageview (load, route change, back/forward) | Yes |
| Custom event (glai(name) or data-glai-event) | Yes |
| Outbound link click | Yes Automatic. |
| Identify call | No Updates the visitor, writes no event. |
| Bots, crawlers, link previews, headless browsers | No Dropped by the user agent list. |
| Visits on localhost | No Unless data-dev="true". |
| Pages in the site's excluded paths | No Set per site in the app. |
| Payments from a webhook | No Free, and kept with their attribution forever. |
Plans differ only in events a month. When a site reaches its allowance, new events stop being recorded until the month ends or the plan is upgraded; nothing already recorded is lost. See pricing for the allowances, or pull your numbers with the stats API.