Pug - Open Source Product Analytics and User Profiles

Pug

7 min read Original article ↗

Open beta: free

Pug records what happens in your product: page views, clicks, scrolls, custom events. Every one is tied to a person.

Ask questions with trends, funnels, retention, and user flows.

Self-host the whole stack, or use the free cloud.

GDPR EU‑hosted Cookieless by default

user-09996

ext cust_009996

Created May 30 First seen 123d ago Last seen 4d ago Android 11 New York City, US

Identified properties1 trait

nameDiana Jones

Recent activitylast 10 events

  • app_close 4d ago
  • scroll 4d ago 72%
  • page_view 4d ago
  • app_open 4d ago
  • checkout_started 4d ago USD 416.21
  • add_to_cart 4d ago prod-0198
  • search 4d ago shirt

Get started

First events in two minutes

Initialize the SDK and auto-tracking starts immediately. No event plan, no instrumentation sprint. It starts cookieless: events flow, nothing is written to the device. Grant consent and identify() merges a signed-in person's anonymous history into their profile.

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

init('your-project-id', { apiKey: 'pub_your_key' })

// Page views, clicks, scrolls, form interactions, rage clicks,
// and dead clicks are captured automatically from here on.
identify('user_123', { email: 'ada@example.com', plan: 'pro' })
track('signup', { plan: 'pro' })
track('order_completed', { amount: 49.0, currency: 'USD' })
import 'package:pug_flutter/pug_flutter.dart';

await Pug.init('your-project-id', const PugOptions(apiKey: 'pub_your_key'));

// Auto-tracking starts immediately. Identify users on sign-in:
await Pug.identify('user_123', traits: {'plan': 'pro'});

// Typed methods for well-known events (custom props go in extras):
Pug.track.signup(extras: {'plan': 'pro'});
import { Pug } from '@pug-sh/node'

const pug = new Pug({ apiKey: process.env.PUG_API_KEY }) // private key, prv_…

// Server events name the user explicitly - no ambient session.
pug.track('user_123', 'order_completed', { amount: 49.0, currency: 'USD' })
await pug.identify('user_123', { email: 'ada@example.com', plan: 'pro' })
// Private keys can also read: profiles and insight queries.
const profile = await pug.profiles.getByExternalId('user_123')

Captured automatically

  • page_view every route change
  • click element, text, selector
  • scroll max depth per page
  • form_submit form interactions
  • rage_click frustration signal
  • dead_click clicks that did nothing

Plus your own

  • signup name any action you care about
  • order_completed with properties, amount, currency
  • video_play queryable like any built-in event

Added on ingest

  • Geo (country, region, city)
  • Device & browser
  • UTM parameters

Every SDK Framework guides What autocapture covers

Live

See events arrive in real time

Every event shows up seconds after it happens, on a live map and in a stream, with the page, device, and location already attached.

  • Ship a tracking change and know within seconds that it fires
  • Watch a launch land as it happens: how many people, from where, on which pages
  • Filter to the event behind a new feature and watch the first real users hit it

Everything you can ask

Pug's Live view: a world map dotted with event markers beside a panel reading 35 live now, filtered by event, device, and country, streaming events as they arrive: cart_viewed for USD 149 in Paris, search_result_clicked in Dubai, screen_view in Santiago, checkout_step_completed in Barcelona. The map zooms to a product_viewed for USD 38 in Melbourne, showing that person's browser, OS, and 7-event session, then to a product_list_viewed on /collections/treats from an iPhone in Bengaluru, each with a link through to the full profile

Unified profiles

One profile per person, however they arrive

The profile you saw at the top of this page is the core of Pug: every session, trait, and event a person ever generated, in one searchable timeline.

  • Before sign-in, events accrue to an anonymous ID
  • identify(userId) merges that history into one profile
  • Works across devices, web today, app tomorrow: same person
  • Traits (plan, email, anything) live on the profile and filter every insight

Analytics per person How identity resolution works

Unified profile user_123

  1. page_view anon
  2. scroll anon
  3. add_to_cart anon
  4. identify('user_123') history joins
  5. signup
  6. order_completed

Insights

Six ways to turn events into answers

Every insight runs over raw events in ClickHouse. Filter by any property, break down by any dimension, and get answers in seconds.

Trends

Time-series of any event. Count, unique users, avg per user, or sum/avg/min/max of a numeric property. Break down by up to 5 properties.

Funnels

Conversion across ordered steps, with drop-off and average time between steps.

Retention

Cohort heatmap from a start event and a return event - who comes back, and when.

Segmentation

One aggregate sliced by any dimension, built for KPI tiles and scorecards.

User flow

A Sankey of the paths users actually take between events, where they go next, where they drop.

Top K

Ranked values of any property (top pages, top referrers, top products), with an “others” bucket.

Trends · signups, last 30 days

Funnel · signup → purchase

Retention · weekly cohorts

Cohort W0W1W2W3W4W5W6 Apr 27 100624841363331 May 4 1005845393532 May 11 10064514438 May 18 100614740 May 25 1006652 Jun 1 10063

User flow · after page_view

page_view 100% of sessions, next step →

What product analytics measures Funnel analysis, explained Retention cohorts, explained

Dashboards

The numbers you check every morning

Pin any insight as a tile. The whole board shares one time window, so every tile answers the same question: how is this period doing against the last one?

  • KPI, line, area, bar, table, and Sankey tiles
  • One time window and granularity for the whole board
  • Period-over-period comparison per tile
  • Thresholds that color a KPI when it crosses a limit
  • Markdown tiles for notes between charts

More on dashboards

Growth board Last 30 days · vs previous

Signups 1,284 +12.4%

Checkout conversion 3.8% −0.4pt

Weekly active users 9,412 +6.1%

Top pages

  • /pricing 4,812
  • /docs/quickstart 3,080
  • /changelog 1,781

MCP server

Ask your analytics from your editor

Pug serves its read-only analytics API as a Model Context Protocol server. Twelve tools, scoped to one project: an agent runs an insight or looks a person up and gets back the same numbers the dashboard would show you.

  • Read-only: no tool creates, changes or deletes anything
  • One project per key, with no way to reach another
  • The same numbers the dashboard shows you
How the MCP server works

MCP session read-only

You

How are signups trending?

query_insights type: trends · window: 30d

Agent

Signups climbed from 12 a day to 78 across the window, and every dip recovered.

Privacy

Nothing on the device until they say yes

Every default here collects less: nothing is written to a visitor’s device before they choose, and the cloud that receives the events runs in the EU.

Cookieless by default

The SDK starts cookieless: events flow, nothing is written to the device. Identity is derived server-side from a salt that is deleted daily rather than rotated - yesterday’s visitors cannot be reconstructed.

Consent you wire yourself

Point your own banner at three states: granted, cookieless, denied. Activity before consent stays anonymous - nothing is retroactively linked when someone later says yes.

Erasure that hard-deletes

One API call erases a data subject by profile id, or by the external id you assigned. Events, sessions, aliases, and the profile are hard-deleted from ClickHouse and Postgres, and you get back a request id to prove it finished.

Privacy & GDPR How cookieless identity works What it costs your funnels Audit your events for PII

Self-host

Run it on your servers, or use ours

The entire pipeline is open source. The same code serves the cloud and your own deployment.

SDK track() & identify()

API Connect RPC ingest

NATS Async pipeline

Workers Geo & enrichment

ClickHouse Analytics store

Dashboard Insights & profiles

Self-hosted

  • One Go binary runs the server and every worker
  • PostgreSQL for accounts and config, ClickHouse for events, NATS for the queue
  • AGPL-3.0: read the code, run it anywhere, your data never leaves

Cloud

  • Managed hosting with zero ops
  • Open beta: free
  • Pricing announced before general availability
See pricing

Self-hosted analytics The open source guide Set it up step by step How the pipeline works Who builds Pug

Coming soon

Customer engagement from the same profiles

Run campaigns on the people you already track, composed from profiles and events and delivered to the channels your users are on.

See the roadmap
  • Web Push
  • Email
  • SMS
  • WhatsApp
  • Android Push
  • iOS Push
  • Webhook

Start tracking today. Own your data forever

Open source, self-hostable, and free during open beta. Create a project and see live events in minutes.

Start free

Questions? Email hello@pug.sh