Skip to content

Quickstart

Send your first event to Pug in under five minutes - install the Web SDK, track a page view, and confirm it in the dashboard.

Updated View as Markdown

Send your first event to Pug in under five minutes. By the end you’ll have the Web SDK installed, a page_view flowing into your project, and confirmation in the dashboard.

Prerequisites

  • A Pug account: sign up at app.pug.sh (or your self-hosted dashboard)
  • Node.js 18+ and a bundler-based web project (Vite, Next.js, etc.)

Building a mobile app? This quickstart is web-only - start with the Flutter setup instead.

Building a backend? Use the server-side Node SDK, or POST events directly from any language - see Integrate over HTTP.

Working with a coding agent? Install with AI has a ready-to-paste prompt for each platform that points the agent at these docs.

1. Create a project and grab your keys

  1. Sign in to the dashboard.
  2. Create an organization, then a project inside it.
  3. Collect the two values this quickstart needs:
    • Project ID: in the dashboard URL: /p/<projectId>.
    • Public key (pub_...): under the API Keys section of your project Overview; safe to ship in client code.

The Web SDK authenticates with your public key. (The same screen also shows a server-side private key - you don’t need it here; see Authentication.)

2. Install the Web SDK

npm install @pug-sh/browser

See Installation for pnpm, yarn, bun, and framework-specific setup. No bundler? Drop in the CDN loader snippet instead.

3. Initialize and track

Call init once at startup, then track anywhere. init registers your project ID and public key and begins auto-tracking (page views, clicks). The first argument to track is the event name - any string you choose.

Vite / React

// src/main.tsx
import { init, track } from '@pug-sh/browser'

init('YOUR_PROJECT_ID', {
  apiKey: 'pub_YOUR_PUBLIC_KEY'
})

track('signup', { plan: 'pro' })

Next.js App Router

init must run in the browser, so wrap it in a client component:

// components/PugProvider.tsx
'use client'

import { init } from '@pug-sh/browser'
import { useEffect } from 'react'

export function PugProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    init(process.env.NEXT_PUBLIC_PUG_PROJECT_ID!, {
      apiKey: process.env.NEXT_PUBLIC_PUG_PUBLIC_KEY!
    })
  }, [])

  return <>{children}</>
}

Add PugProvider to your root layout and store the values in .env.local:

NEXT_PUBLIC_PUG_PROJECT_ID=your-project-id
NEXT_PUBLIC_PUG_PUBLIC_KEY=pub_your_public_key

Only ever expose the public key with NEXT_PUBLIC_*. The private key stays server-side.

4. Verify in the dashboard

  1. Open your project in the dashboard.
  2. Go to Live - the active visitor count should tick up within a few seconds.
  3. Go to Events - page_view (auto-tracked on init) and your signup event should appear.

Events are batched client-side and flushed every few seconds, so allow up to ~10 seconds for the first one. Force an immediate send with track('signup', {}, { immediate: true }).

5. Identify a user (optional)

After sign-in, link anonymous activity to a known user. This step needs granted consent - there is no anonymous ID to merge while the default cookieless state is in force, so call optInTracking() once the user has agreed:

import { identify, optInTracking } from '@pug-sh/browser'

optInTracking()
await identify('user-123', { email: 'user@example.com', plan: 'pro' })

identify() returns a promise and never throws (invalid input, a missing identifier and transport failures are logged and the promise resolves), so you can await it without a try/catch. On sign-out, call reset() to start a fresh anonymous session. See Identity & sessions.

You’re done when…

  • page_view and signup appear in Live and Events
  • Auto-tracked clicks/scrolls appear (defaults are on)
  • identify() merges pre-login events into a profile (optional - needs granted consent)

Common issues

Symptom Likely cause Fix
No events in dashboard Wrong project ID or public key Re-check the API Keys section of your project Overview
Events in console but not dashboard dryRun: true in init options Remove dryRun or set false
CORS errors in the browser Wrong endpoint Use https://api.pugs.dev or your self-hosted URL
Nothing happens, no errors init() ran outside the browser (SSR) Call init() in a client component / useEffect
Events delayed Client-side batching Normal (see step 4) - or use { immediate: true }
identify() does nothing, warns once Consent is cookieless (the default) - no stored ID to merge optInTracking() after the user agrees; see Tracking consent
Event counts look right, unique-user counts look low Cookieless IDs rotate daily, so unique-user metrics, funnels and retention exclude them by default Expected before consent; see include_cookieless

Next steps

Next: Core concepts - orgs, projects, keys, and the event pipeline. Then:

Navigation

Type to search...

↑↓ navigate↵ selectEsc close