Skip to main content
An event is one thing that happened in your application: a click, a page view, a purchase. You send an event with track. Both SDKs queue events, send them in batches, and retry on failure. This page covers custom events. Events that Grain collects without code are on Automatic tracking.
The first argument is the event name. The second argument is an object of properties. In the Grain Tag, track returns nothing and is safe to call before init. The call is queued and replayed after init runs. In Analytics Web, track returns a promise that resolves when the event is in the queue. Read Name events for the naming convention. The TypeScript types of the published packages win over this page when they disagree.

Properties

Properties answer the questions “which one” and “how much”. Grain adds device, browser, and attribution properties to every event on its own. Read Automatic properties.
  1. Include the identifiers and amounts that a query needs: product_id, total, plan.
  2. Use one naming style for every property. The site uses snake_case.
  3. Do not send passwords, card numbers, or other personal data.
  4. Put data in properties, not in the event name. product_viewed with product_id: 'SKU123', not product_SKU123_viewed.

Batching

Both SDKs collect events in a queue and send the queue as one request. The queue flushes every 5 seconds, or when it holds 50 events, whichever comes first.
Read Configuration options for every option and its default.

Flush the queue

flush sends the queue now and resolves when the request is complete. Call it before a serverless function returns, and after a purchase or a signup.
In Analytics Web, track accepts a third argument of type SendEventOptions. When flush is true, the SDK sends the queue as soon as the event is in it. The Grain Tag track has no options argument. Call flush on the instance instead.
Analytics Web

Page unload

The Grain Tag listens for beforeunload, pagehide, and visibilitychange. When one of them fires, it sends the queue with the Beacon API. Analytics Web does the same on beforeunload. Do not add your own unload listener for Grain events.

Delivery and retry

  1. You call track. The SDK adds the event to the queue.
  2. The queue reaches batchSize events, or flushInterval passes, or you call flush.
  3. The SDK sends the batch to the Grain API.
  4. If the request fails, the SDK retries up to retryAttempts times with exponential backoff.
  5. When a request succeeds, the events are stored and appear in the dashboard.
Read Errors and retries for what happens after the last retry.

Attach a user

Events without a user ID are anonymous. Call identify after login, and every later event carries the user ID. Read Identify users.

Debug logging

Set debug: true in the configuration of either SDK. The SDK then logs queueing, batching, requests, and responses to the browser console. For the Grain Tag, you can also add ?grain_debug=1 to the page URL. This turns on the same logs without a code change.

Rules for the client

  1. Do not track page views by hand when automatic page views are on. Both SDKs track them, including History API navigation. Read Automatic tracking.
  2. Do not start an event name with _grain_. The prefix is reserved for system events.
  3. Call flush before a process exits. A serverless function ends before the flush timer fires.
  4. In Analytics Web, pass { flush: true } for an event that must leave the page now, such as a form submit that navigates away.
  5. Do not retry a track call yourself. The SDK retries retryAttempts times.
  6. In the Grain Tag, import { track } from '@grainql/tag' has no side effects. Outside a browser it returns a no-op, so a server render does not need a guard.