All docs

JavaScript SDK

Send events and identify users to Get Butters straight from the browser with @getbutters/js, without writing your own fetch calls.

The Get Butters JavaScript SDK (@getbutters/js) lets you send events and identify users straight from a web page, without hand-writing fetch calls or handling the user id yourself.

Install

Install it from npm:

npm install @getbutters/js

Then import and initialize it:

import { init, track, identify, reset } from '@getbutters/js'

init({ key: 'pk_...' })

If you don't use a build step, load it with a script tag instead:

<script src="https://cdn.jsdelivr.net/npm/@getbutters/js@0.1.0/dist/butters.min.js"></script>
<script>
  butters.init({ key: 'pk_...' })
</script>

Always pin the exact version in the script URL, as shown above, rather than using @latest. That way a new release of the SDK can't change what runs on your site until you choose to update it.

For extra protection against a compromised CDN, add a Subresource Integrity hash to the script tag. With it set, the browser refuses to run the file if its contents don't match, so a compromised CDN can't swap the script out from under you. The hash below is for version 0.1.0; each release has its own, so update both together when you upgrade:

<script src="https://cdn.jsdelivr.net/npm/@getbutters/js@0.1.0/dist/butters.min.js"
  integrity="sha384-geGe4yu6p4q4Q3ID8f7qkUSz2BVS7fQ9/c+YK77G7JUiXL7jRAEbgq4gFDkAPXrh"
  crossorigin="anonymous"></script>

Get a publishable key

  1. Open the API page in your Get Butters dashboard.
  2. Find the Publishable keys card.
  3. Click to create a new key, choose the project it should write to, and optionally list the origins (websites) allowed to use it.
  4. Copy the key. It starts with pk_ and is shown only once.

When the key is created, the dashboard also shows a ready-to-paste script tag with your key already filled in.

Always use a publishable key (pk_...) in the browser, never a secret key (ev_...). A publishable key can only send events and identify users for the one project it belongs to, and it can't trigger notifications or backdate events. If you set allowed origins on the key, requests from any other site are rejected.

Initialize the SDK

Call init() once, as early as possible on every page:

init({
  key: 'pk_...', // required, your publishable key
  host: 'https://app.getbutters.com', // optional, only needed for a self-hosted instance
  pageviews: false, // optional, turn on automatic pageview tracking
  debug: false, // optional, log problems to the console
})

init() must run before anything else in the SDK will do anything. Calls to track() or identify() made before init() are silently ignored, so double check that init() runs first on every page.

Calling init() a second time on the same page is ignored. Only the first call takes effect.

Track an event

track('order', 'Checkout completed', {
  description: 'Plan upgraded to Pro',
  icon: '🎉',
  tags: { plan: 'pro' },
  metadata: { amount: 4900 },
  url: 'https://example.com/checkout',
})

If you've called identify() on this page, the event is automatically attached to that user. Events sent before identify() runs have no user attached.

Identify a user

identify('user_123', { email: 'ada@example.com', plan: 'pro' })

The user id must be between 1 and 200 characters. A longer id is rejected and nothing is sent.

Anyone who can run JavaScript on your page can call identify() with any user id and any properties they like, since this call comes from the browser. Treat it as unverified input. Use it for cosmetic details like a theme or last-viewed page, never for anything you'd act on, like a plan, an email address, or anything tied to billing or access control. Set those from your own server with a secret key instead.

Reset on logout

reset()

Call reset() from your logout handler. It forgets the identified user on this device, so the next person who uses a shared computer isn't attributed to the previous visitor.

Automatic pageviews

Pageview tracking is off by default. Turn it on in init():

init({ key: 'pk_...', pageviews: true })

Once it's on, a pageview event fires when the page loads and again every time the visitor navigates to a new path, including single-page apps that update the URL without a full reload.

A few things to know about what gets sent:

Only the page path is used as the event title, never the full URL with query parameters.

Any tracking parameters starting with utm_ are kept; everything else in the query string is dropped, since it can carry tokens or personal data.

The page referrer is only sent for the first pageview of a visit, and only when it came from another site.

No user agent, screen size, language, location, or session id is ever collected.

If your site uses hash-based routing (URLs like /#/route), only the very first pageview is tracked, since the path itself never changes.

Each pageview counts as one event toward your project's monthly quota, the same as any event sent with track().

Limits

A publishable key can send up to 60 requests per minute, shared between track() and identify() together and counted per key and per visitor IP address. If you go over that limit, the SDK's requests will start failing until the next minute; turn on debug: true to see this happening.

Content Security Policy

If your site sets a Content Security Policy, add these directives so the SDK can reach Get Butters and, if you use the script tag, load the SDK itself from jsDelivr:

Content-Security-Policy: connect-src https://app.getbutters.com; script-src cdn.jsdelivr.net

Use your own host value instead of https://app.getbutters.com if you set one in init().

Works safely with server-rendered pages

The SDK is safe to import in an app that renders on the server, like Next.js or Astro in SSR mode. Every function checks that it's actually running in a browser first, so importing or calling it during a server render simply does nothing. It never throws an error.

Troubleshooting

If events or identified users aren't showing up in your Get Butters feed, turn on debug logging first:

init({ key: 'pk_...', debug: true })

With debug: true, the SDK logs problems to your browser console prefixed with [butters]. Without it, the SDK fails silently on purpose, so a misconfigured key never breaks your site for visitors.

Then check, in order:

Make sure init() is only called once, and that it runs before any track() or identify() calls.

Confirm you're using a publishable key (starting with pk_), not a secret key (starting with ev_).

If you set allowed origins on the key, confirm the page's domain is on that list.

Check whether you've hit the 60-requests-per-minute limit for that key and IP address.

If you're still stuck, contact support with your project name and the console output from debug: true.