Documentation

Set up Lantern in two lines

One rewrite on your host and one script tag, or one prompt to your coding agent. Lantern starts counting visitors, sources, AI referrals and goals within a minute, with nothing else to configure.

Set up with an AI agent#

The fastest way: let your coding agent (Claude Code, Codex, Cursor, or any agent that can edit your repository) do the install. It adds the rewrite and the script for your framework, then reads your code to find your main KPI, the funnel leading to it and the first actions that show a user is activated, and instruments those goals where they actually succeed. Nothing to name or configure in Lantern; goals show up as soon as they fire.

Copy the prompt from your site's Install panel (it has your site id filled in), or use this one:

Prompt
Set up Lantern analytics in this project and instrument its key goals.
Site ID: site_xxxxxxxxxxxx
Domain: yourdomain.com
Follow the instructions at https://visitlantern.com/setup.md?site=site_xxxxxxxxxxxx&domain=yourdomain.com

The agent writes lantern-tracking-plan.md with the goals and funnels it added, so you can review every event before you deploy. It doesn't commit or deploy unless you ask.

Agent without web access? The instructions are plain Markdown at https://visitlantern.com/setup.md; paste them in directly (the Install panel has a button that copies them with your site filled in).

Claude Code skill

Install it once and set up any project with a single command:

Terminal
mkdir -p ~/.claude/skills/pulse-setup && curl -fsSL https://visitlantern.com/skill.md -o ~/.claude/skills/pulse-setup/SKILL.md
Claude Code, in your project
/pulse-setup site site_xxxxxxxxxxxx on yourdomain.com

Install manually#

Add a site in the dashboard to get its data-site id; the install panel there shows these snippets with your id filled in. Pick your host:

1. Add the rewrite

next.config.ts
const nextConfig = {
  async rewrites() {
    return [{ source: "/_p/:path*", destination: "https://api.visitlantern.com/:path*" }];
  },
};

2. Add the script

app/layout.tsx
import Script from "next/script";

// inside <body>
<Script src="/_p/script.js" data-site="site_xxxxxxxxxxxx" data-domain="yourdomain.com" strategy="afterInteractive" />

Already have rewrites? Add the one entry to your existing array.

That's the whole setup. Deploy, open your site, and the visit shows up on the dashboard and the live globe within seconds.

Why a rewrite#

Ad blockers and privacy browsers (uBlock Origin, Brave, Safari's tracking protection) block scripts from known analytics domains. On sites with a technical audience that's often 20–40% of visitors, and they vanish from your numbers without any error.

The rewrite serves Lantern from yourdomain.com/_p, which is your own domain, so there's nothing to block. The script sends its events back through the same path, so the one rule covers both. Visitor locations stay accurate: your host forwards the visitor's IP, and Lantern uses it only to look up the city.

/_p is a suggestion; any unused path works if you change it in both the rewrite and the script's src.

Check it works#

After adding the site, the dashboard's install panel waits for your first pageview and confirms it. It also tells you whether the script is being served from your domain, so you know the rewrite works.

To check by hand, open your site with the browser's developer tools on the Network tab:

RequestExpect
/_p/script.js200, JavaScript (not your site's HTML or a 404: that means the rewrite isn't active yet)
/_p/api/event202 for each pageview
Visits from localhost and from domains other than your site's are ignored, so local development and preview deployments on another domain don't pollute your numbers. Subdomains of your site, like app.yourdomain.com, are counted.

Goals & events#

Pageviews, sources, time on page and scroll depth are automatic. Track the moments that matter to your business as goals; they show up in the Goals card and on the live globe.

Anywhere in your app
// Goals and custom events
pulse("track", "signup", { plan: "pro" })

// Tie the anonymous visitor to your user after sign-in
pulse("identify", user.id)

// Or without JavaScript: count clicks on any element
<button data-pulse-goal="signup_click" data-pulse-plan="pro">Sign up</button>

Event names are up to 120 characters; each event takes up to 30 properties with string, number or boolean values. To call pulse() before the script has loaded (for example, from inline code at the top of the page), add the queue stub first:

<head>, before your own code
<script>window.pulse = window.pulse || function () { (pulse.q = pulse.q || []).push(arguments) };</script>

Identify users#

Visitors are anonymous. When someone signs in or signs up, call identify with your own user id. Their visits from then on carry that id, alongside the anonymous visitor id from before, so you can trace what first brought each customer.

After sign-in
pulse("identify", user.id, { plan: "pro" })

Use an internal id rather than an email address, so no personal data is sent to Lantern.

Revenue#

Record a payment from the browser, for example on your checkout success page:

Checkout success
pulse("revenue", 49, "USD", { plan: "pro" })

For payments confirmed on your server, pass pulse.visitorId() to your payment provider (for example as Stripe checkout metadata) so the payment can be tied back to the visit. Automatic Stripe attribution is on the roadmap.

Subdomains#

With data-domain="yourdomain.com" on the script (the install snippet includes it), the visitor id is stored in a cookie shared by all your subdomains. Someone who reads your blog on yourdomain.com and signs up on app.yourdomain.com is counted as one person with one source. Add the same script, with the same data-site, on every subdomain.

Single-page apps#

Client-side navigation in Next.js, React Router, Vue Router, SvelteKit and similar is tracked automatically: Lantern listens to the browser's history changes and records a pageview for each new URL. No router integration is needed.

AI crawlers#

GPTBot, ClaudeBot, PerplexityBot and other crawlers never run JavaScript, so the script can't see them. To find out which pages AI tools read, report crawler requests from your server. The install panel in the dashboard has a ready-made Next.js snippet with your site's secret; for other servers, send requests from crawler user agents to:

POST, from your server
POST https://api.visitlantern.com/api/bot
Authorization: Bearer <your site's bot secret>
Content-Type: application/json

{ "ua": "<user-agent>", "url": "<full page URL>", "ip": "<client IP>" }

Up to 500 hits per request as a JSON array. Human user agents are ignored, so it's safe to over-send.

Script attributes#

AttributeDescription
data-siteRequired. Your site id from the dashboard.
data-domainYour root domain. Shares the visitor id across subdomains.
data-apiWhere to send events. Defaults to wherever the script was loaded from, so you only need it for unusual proxy setups.
data-allow-localRun on localhost. Only useful with a local Lantern server; the hosted service ignores localhost.

JavaScript API#

CallDescription
pulse("track", name, props?)Records a goal or custom event.
pulse("identify", userId, traits?)Links this visitor to your user id.
pulse("revenue", amount, currency?, props?)Records a payment. Currency defaults to USD.
pulse.visitorId()The anonymous visitor id, for server-side attribution.
data-pulse-goal="name"On any element: records the goal when it's clicked. Other data-pulse-* attributes become properties.

Privacy & data#

  • One first-party cookie, _pulse_vid, holds a random visitor id on your own domain. There are no third-party cookies and no tracking across other websites.
  • IP addresses are used once, when the event arrives, to look up the city and network, and are never stored. Locations are approximate (mobile carriers in particular often resolve to a nearby city).
  • Automated browsers are skipped, and known bots are kept out of visitor counts.
  • Events are stored on Google Cloud in the United States.

IP geolocation by DB-IP

Troubleshooting#

SymptomFix
No visits at allOpen yourdomain.com/_p/script.js. If it isn't JavaScript, the rewrite isn't deployed yet. Also check that data-site matches the dashboard and the site's domain matches where the script runs.
Works locally, nothing in productionLocalhost is ignored by design. Test on your deployed site, or on a subdomain of it.
Fewer visitors than expectedYou're probably loading the script from our domain. Add the rewrite so ad blockers don't hide visitors.
Blocked by Content Security PolicyWith the rewrite, 'self' already covers Lantern. Without it, add https://api.visitlantern.com to script-src and connect-src.