Frequently asked questions
Answers about accounts, tracking, revenue, data, the API and self-hosting.
Accounts
How do I get an account?
Sign up at /signup with your email address and open the confirmation link PilotFox emails you. Open it in the
browser you signed up in to keep the password you chose. Opened on another device or in another browser, it still
verifies your address and signs you in, but without a password: choose one with Forgot password on the sign-in
page. Your account comes with its own organization, with you as its owner. If someone invited you, open their
invitation instead: you join their organization and get none of your own.
On a self-hosted instance, sign-up is open only when the instance has mail configured (Cloudflare Email Sending or
SMTP_URL) and SIGNUP_POLICY is open, its default; otherwise accounts come from invitations, or from a system
admin. See Sign-up and email.
How do I change my email address?
On your Account page, choose Change next to your email and enter the new address. PilotFox emails a confirmation
link to your current address; opening it sends a link to the new address, and your email changes when you open that
one. Open both links in a browser where you are signed in to your account: they do nothing for anyone who isn't. The
confirmation link works once. The email to the new address names your account by its current address, partly hidden
(for example a***@example.com). A self-hosted instance offers this only when it has mail configured (Cloudflare
Email Sending or SMTP_URL).
How do I add my team?
In Organization settings → Members, an owner or admin invites people by email, each with one of five roles (owner, admin, editor, member, viewer; never one above the inviter's own) and, if you like, access to only some sites. People you invite sign up, or sign in, from the link in the invitation email; an invitation is valid for 7 days. One account can belong to several organizations. What each role may do is in Permissions.
How do I delete my account?
At the bottom of your Account page, Delete account shows what goes with it first, and confirms with your password and your email address typed out. An account without a password (Google, GitHub or emailed codes) signs in again first and then has 10 minutes. What it deletes, and what stops it, is in Deleting an account.
Tracking
How does PilotFox tell visitors apart without cookies?
The server hashes a secret value kept per site, the site's id, the visitor's IP address and their browser's user agent into a visitor id. The IP address itself is never stored, and the same person gets unrelated ids on different sites. See Privacy.
How long is a session?
A session lasts until 30 minutes pass without an event from the visitor. Identifying a user in the middle of a session does not start a new one.
Are bots counted in my numbers?
No, by default. Requests flagged by the bot checks (user agent, request headers, browser signals, network and request rate) are left out of your reports and shown in the Bots report instead. Site settings → Bots can keep them in.
How do I keep my own visits out of the reports?
Add your IP address or range under Site settings → Exclusions, or run pilotfox.optOut() in the browser console on
your site; pilotfox.optIn() undoes it. See Opt-out and excluding traffic.
Does PilotFox respect Global Privacy Control?
Yes. Browsers that send the GPC signal are not tracked unless you turn this off in Site settings → Privacy & identity. PilotFox reads the GPC signal, not the older Do Not Track header.
Can one site cover several domains or subdomains?
Yes. The script sends the full page URL, so the hostname is recorded with every event and can be used as a filter. To accept events from listed hostnames only, set Allowed hostnames in Site settings → Privacy & identity.
How big is the tracking script?
Under 10 KB compressed: its build fails above a 9 344-byte gzip budget. It loads with defer, sets no cookies and
sends each pageview or event as one small request. The session replay recorder is a separate file (/api/r.js),
loaded only on tabs that are recorded. See Install the script.
Revenue
Which payments does PilotFox import?
Payments from Stripe, Dodo Payments or Polar that were actually paid, with their full and partial refunds. From Stripe: paid Checkout Sessions, including those created by Payment Links, and, when the key has Read access to Invoices, every paid subscription invoice (renewals included); payments made without Checkout or a subscription, such as PaymentIntents you create yourself or one-off invoices, are not imported. From Dodo Payments: succeeded payments, renewals included. From Polar: paid orders, renewals included. Your own billing system can record payments through the payments API. See Revenue and each provider's page.
Why is a payment not linked to a visit?
A payment is linked when a checkout reference it carries (its metadata.pilotfox_ref, or a reference the script
added to a payment link) matches the ref of a checkout event sent in the 7 days before it, or its return page sent
the payment's own id; when a user id it carries (such as metadata.pilotfox_user_id) matches a user you identified;
when the customer's email matches the email trait your server sent for a user (an email set only in the browser
does not count); or when the same customer paid before through the same provider and that payment is linked. A
subscription's renewals follow its first linked payment. If none of these match, the payment still counts in your
revenue totals, but not in filtered reports or per-source breakdowns. Payments a provider's sync imported before you set
this up are linked after Match again. See Attribution.
Which visit gets the credit for a payment?
By default the latest visit that came from somewhere (a search, a link, an ad, an email) within 90 days before the payment, so a buyer who found you through a search and came back by typing your address is counted under the search. You can credit the first visit or the last visit instead, and change the lookback window (1 to 365 days), in Site settings → Revenue; the reports change at once.
Does PilotFox convert currencies?
No. Each payment keeps its own currency, and reports show one currency at a time: the site's default currency, or another one picked on the Revenue page.
Data
Which analytics tools can I import data from?
Umami (CSV), Simple Analytics (CSV), Plausible (CSV ZIP) and PilotFox's own export (JSONL), in Site settings → Import & export. Plausible exports hold daily totals, so PilotFox creates approximate events from them and marks the import as approximate. Imports need object storage (R2) on a self-hosted instance.
Can I export my data?
Yes. Site settings → Import & export downloads a site's raw events as JSON Lines (NDJSON) for up to 400 days at a
time, and the same export is available through the API
(GET /api/v1/sites/{siteId}/export). Exports need the editor
role, or an API key with the exports:read permission, because they contain visitor and user ids.
Can I share a dashboard with someone who has no account?
Yes. A share link gives read-only access to one site's dashboard, can expire, and includes sessions, users or replays only if you choose so. A public dashboard shows traffic statistics to anyone with its link, never sessions, users or replays. Affiliates get their own portal.
How do I delete a person's data?
Open the user in the Users report and choose Delete user data (editors and above), or call
DELETE /api/v1/sites/{siteId}/users/{userId} with an API key that has users:delete. Their events, sessions,
replays, identity links and traits are erased in a background job; their payments stay in your revenue totals without
any link to them. See Access and deletion.
What happens when I delete a site?
Its events, session recordings, payments, goals, funnels, share links, Search Console data and settings are erased. This cannot be undone.
Developers
Should I use an API key or OAuth?
Use an API key for the REST API and for server-side ingest. Organization admins and owners create keys in
Organization settings → API keys (or with
POST /api/v1/orgs/{orgId}/api-keys), limited to the
permissions and, optionally, the sites you choose, with an optional expiry. Send it as Authorization: Bearer ak_… or
in the x-api-key header, from your server only. See Authentication.
OAuth is for MCP clients only: an assistant connected to /api/mcp can sign you in with OAuth instead of holding
an API key, and then acts as you in one organization, with at most the access you granted it. OAuth tokens are not
accepted by the REST API. See MCP with OAuth and MCP with an API key.
How many API keys can an organization have?
50 active (unexpired) keys by default. One more is refused with 409 until one is deleted; a self-hosted instance can
change the cap with API_KEY_MAX_PER_ORG.
What are the rate limits?
Each API key, signed-in user and share link gets 600 reads (GET, HEAD) and 60 writes a minute on /api/v1, and a
few routes have a budget of their own. Past it the API answers 429 with the error code rate_limited and a
Retry-After header in seconds. See Rate limits.
Can I call the API from a browser?
Not from another website. The REST API (/api/v1) and /api/auth send CORS headers only to the instance's own
origin (PUBLIC_URL) and the origins listed in DASHBOARD_ORIGINS, so a browser on any other origin cannot read its
answers: call it from your server, which also keeps your API key secret. The tracking script's endpoints and the map
boundary tiles allow every origin, without credentials.
Where is the OpenAPI document?
Every instance serves it at /api/docs/openapi.json (OpenAPI 3.1), with an interactive reference at /api/docs/.
The API reference in these docs is generated from the same document.
Is a self-hosted instance the same as pilotfox.app?
It runs the same API, web app and tracking script. Replace https://pilotfox.app in every example with the
instance's PUBLIC_URL: the API paths, the tracking script (/api/s.js) and the MCP endpoint (/api/mcp) are the
same. What differs is configuration: who may sign up, the limits its operator set, and the optional services it has
(mail, GeoIP, object storage for replay and imports, Search Console).
Self-hosting
What do I need to run PilotFox myself?
A Linux server with Docker and its Compose plugin (8 GB of RAM for the default limits), a PostgreSQL 17 database, and a Cloudflare account with your domain: the web app runs as a Cloudflare Worker and visitors reach the server through a Cloudflare Tunnel, so the server opens no port. Mail, a MaxMind account, a Cloudflare R2 bucket and a Google OAuth client are optional. See Requirements and Deploy with Docker Compose.
Does it work without MaxMind, mail or R2?
Yes. Without MaxMind, visitor locations stay empty (unless Cloudflare's headers provide them). Without mail, sign-up is invite-only and an inviter gets the invite link to pass on. Without R2, there is no session replay, no imports and no backups.
How do I back it up?
Set the four R2_* values, then turn on the schedule under Admin → Backups. Run a restore drill regularly, and keep a
copy of your secrets (.env or Doppler) off the server: backups are useless without them. See
Backups and restore.