Privatrak

Documentation

Set up Privatrak, name what matters to you and read every report.

Watch the video seriesEight short videos covering the whole product, on YouTube.Opens in a new tab

MCP reference

Everything developers need about Privatrak’s MCP server: the address, sign-in and API keys, every tool and prompt, and how changes are grouped so they undo in one step. To connect an assistant, start with Connect an AI assistant.

Endpoint and transport

  • URL: https://api.privatrak.com/mcp. One address serves all your projects. A connection made by signing in can cover several projects, an API key exactly one.
  • Transport: Streamable HTTP. The server accepts every protocol version from 2024-11-05 to 2026-07-28. Send every message as a POST with Content-Type: application/json and Accept: application/json, text/event-stream. Without both types in Accept the server answers 400. Answers come back as plain JSON.
  • Stateless: the server keeps nothing between requests and issues no Mcp-Session-Id, so every request stands on its own. GET and DELETE on /mcp answer 405, because there is no session stream to open or close.
  • CORS: /mcp allows any origin, without credentials, and request headers including Authorization, X-API-Key, Mcp-Protocol-Version and Mcp-Session-Id. It exposes WWW-Authenticate, so browser-based clients such as MCP Inspector can start the OAuth flow.

Authentication

/mcp accepts two kinds of credential: an OAuth access token, issued when a user signs in, or one of a project’s API keys. Send either as Authorization: Bearer TOKEN.

OAuth

  • Flow: OAuth 2.1 authorization code with PKCE, S256 only. Clients are public (token_endpoint_auth_method: none). There is no client secret and no implicit, password or client credentials grant.
  • Discovery: every 401 from /mcp names the protected resource metadata (RFC 9728) in WWW-Authenticate, at https://api.privatrak.com/.well-known/oauth-protected-resource/mcp. It points to the authorization server, whose metadata (RFC 8414) is at /.well-known/oauth-authorization-server. The endpoints are /oauth/authorize, /oauth/token, /oauth/register and /oauth/revoke.
  • Client registration: a Client ID Metadata Document, meaning an https client_id whose URL serves the client’s metadata, or Dynamic Client Registration (RFC 7591) at /oauth/register. Claude uses the first, Cursor and Codex the second.
  • Scopes: read and write, where write includes read. A request without a scope gets read. offline_access is accepted and changes nothing, because every connection gets a refresh token.
  • Consent: the user chooses the projects, either All my projects (including ones created or joined later) or Only these, and the access, Read or Read and write. Read and write is offered when the client asked for write. What the user sees is described in Connect an AI assistant.
  • Tokens: access tokens last 1 hour and are bound to the resource https://api.privatrak.com/mcp (RFC 8707), so the REST API does not accept them. Refresh tokens rotate on every use and expire after 30 days unused.
  • Access: read gets the same tools as an AI assistant key. write adds the write tools, the setup run tools and the setup_project prompt, the same write access as a full access key.
  • Revocation: the user disconnects a client under Settings › Account › Connected AI apps, which ends its tokens at once. A client can revoke its own tokens at /oauth/revoke (RFC 7009).

API keys

Send one of a project’s API keys as Authorization: Bearer YOUR_KEY or X-API-Key: YOUR_KEY. Both headers with different keys are a 401. A key belongs to one project, and what it may do depends on its kind:

  • Your AI assistant (type read): every read tool, the product_review prompt and the guide. It can change nothing, and it cannot see members, billing or other keys.
  • Full access (type secret): also every write tool, the setup run tools and the setup_project prompt.
  • Your website (type public): refused, because it sits in your page source where anyone can read it.

These requests get 401: no credential, an unknown, expired or revoked one, or a website key. The answer carries WWW-Authenticate: Bearer realm="privatrak" and the resource_metadata URL, plus error="invalid_token" when a credential was sent. The JSON body’s error says what was wrong and its error_code is auth_invalid_token. If the credential cannot be checked because the service is briefly unavailable, the answer is 503, and retrying is safe.

Projects

Every tool and prompt that answers about one project takes an optional project argument, a project ID from list_projects. The server keeps no current project between calls.

  • A connection that covers one project may leave it out, and so may every API key. An API key refuses any project but its own.
  • When a connection covers more than one project, a call without project is a tool error that lists them, so the assistant asks the user instead of guessing. Project membership is checked on every call.
  • list_projects returns each project’s ID, name, timezone and access. For an API key it lists the key’s one project.

Rate limit

Each API key and each connection may send a burst of 60 requests, refilled at one request every two seconds. Beyond that the server answers 429 with Retry-After: 2 and error_code mcp_rate_limited. Every request counts, tools/list included.

Data conventions

  • Dates are YYYY-MM-DD calendar days in the project’s timezone, which get_project returns. Timestamps in answers are UTC.
  • Default range: the last 28 complete days, ending yesterday. Every answer says which period it used in period. A to in the future is cut at today and marked clamped_to_today. A from after today is an error.
  • Coverage: a period that starts before the project has complete data is marked starts_before_data with data_from, and no percentage change is computed against it. Week and month buckets that cover only part of their span are marked partial.
  • Counts: unique_sessions are visitors counted once per day, so over a longer range one person can be counted on several days. Counts from list_elements, preview_feature_rule and preview_funnel are events, not visitors. Counts from list_click_problems are page views: each problem counts once per element per page view.
  • Range cap: those three tools read raw events and accept at most 92 days per call, and so does list_click_problems.
  • Hours: run_insights_query with group_by hour and get_feature_timeseries with granularity hour return the hours of the project’s timezone. A day the clocks change has 23 or 25 hours. Both accept at most 31 days, from and to included.

Results and errors

  • A tool result carries its data as structuredContent and the same JSON as text, for clients that only read text. No output schemas are published.
  • When the API refuses a call, for example an unknown funnel or an invalid filter, the result has isError: true and the API’s own message as text, so the assistant can correct itself.
  • Arguments are checked against the tool’s input schema before anything runs. Unknown arguments are rejected, not ignored, and an unknown tool is a JSON-RPC error.

Tools

Your client gets every tool with its full input schema from tools/list. The tools carry MCP’s hints: reading tools are marked readOnlyHint, and tools that change or delete something are marked destructiveHint, which clients use to ask you before running them. openWorldHint is false throughout, because the tools only ever touch the one project.

Reading, with every connection and key

ToolWhat it does
list_projectsThe projects this connection can use, with each one’s ID, name, timezone and access.
get_projectOne project: name, timezone, plan, retention, today’s date, limits and slots left.
get_overviewHeadline numbers against the previous period, a daily series, top pages and features.
list_featuresFeatures ranked by use, optionally compared with the previous period, including features that stopped.
get_feature_timeseriesUse of the top features per day or per hour.
list_funnelsSaved funnels with a rough conversion over the last 31 days.
get_funnelOne funnel’s steps for a period, with drop-off and the worst step.
get_funnel_trendA funnel’s conversion per day, week, month or year.
preview_funnelHow many events each draft step matches, before a funnel is created.
list_sourcesWhere visitors came from, most first: search engines, social media, AI assistants, other websites and campaign links. Visitors who came directly or from an unknown place share one row. It also lists the pages they landed on. Each visitor counts once a day, for their first page that day.
list_campaignsVisitors who came through your campaign links, most first. One row per campaign name, source and medium, with its top link variants, search terms and the pages they landed on.
list_pagesPages ranked by views, with entries: how many visitors started their day on each page. Views count page views, not visitors. A page is its site address plus its path, so addresses that differ only after a question mark are one page.
get_flowWhat visitors did next, as a tree of up to four steps.
find_flow_nodesSearch the pages and features that appear in user paths.
run_insights_queryCount events per hour, day, week or month, with filters and one breakdown.
list_dashboardsSaved dashboards.
get_dashboardOne dashboard and its widgets’ queries.
list_feature_rulesThe rules that name events as features.
preview_feature_ruleWhat a draft rule would count, and which other features already count some of the same events.
list_elementsWhat people clicked and submitted, grouped, with the features each counts towards.
list_click_problemsElements where clicks went wrong (no effect, repeated clicks, errors, slow responses), worst first, with the status of each. Each problem counts once per page view.
list_property_keysProperties available for filters and breakdowns.
list_property_valuesThe values a property has taken.
search_docsSearch Privatrak’s documentation and get the matching sections with links.
read_docs_pageRead one documentation page in full.

Changing, with write access

Write access has two sources: an OAuth connection where the user chose Read and write, or a full access key. Both allow the same tools.

ToolWhat it doesMarked destructive
create_feature_ruleSave a feature rule.no
update_feature_ruleReplace a rule’s name and conditions.yes
delete_feature_ruleDelete a rule.yes
create_funnelSave a funnel of 2 to 10 steps.no
rename_funnelRename a funnel. Its steps cannot change.yes
delete_funnelDelete a funnel and the days it has counted.yes
create_dashboardCreate an empty dashboard.no
rename_dashboardRename a dashboard.yes
delete_dashboardDelete a dashboard and its widgets.yes
add_widgetAdd a chart to a dashboard.no
update_widgetChange a widget’s title, query or position.yes
remove_widgetRemove a widget.yes
resolve_click_problemMark a click problem as fixed. If a click on it does nothing again or causes an error again, it comes back as Happened again.yes
ignore_click_problemMark a click problem as meant to be like that. It stays hidden for good.yes
reopen_click_problemTake back resolving or ignoring, so the element is listed as open again.yes

Setup runs, with write access

ToolWhat it doesMarked destructive
start_setup_runStart a group of changes that undoes in one step.no
list_setup_runsEarlier setup runs and what each changed.no
get_setup_runOne run’s changes, before and after.no
undo_setup_runUndo a run, as a dry run by default.yes

The three click problem tools take a row’s identity from list_click_problems: all five fields exactly as returned, null where it is null. An identity with a field left out is refused, because it would name no real element. Rows listed with group_by: selector carry no identity. Resolving and ignoring only hide a row. No count changes, and no event is deleted.

Prompts and resources

  • product_review, with the optional arguments from, to and project, in that order: a fixed review of the overall change, the features that moved most, funnel drop-offs, the most-used elements no feature counts yet, and what to look at next. The review is described in Ask about your data. Every connection and key.
  • setup_project, with the optional arguments instrument, focus and project, in that order. instrument is code (data-track in the code, as a change to review), rules (feature rules only: the code is never edited, and no change to it is proposed) or empty to let the assistant choose. focus names what matters most. The method is described in Let it set up your project. Write access only.
  • privatrak://guide/instrumentation (Markdown): how the tracker names things, how feature rules differ from data-track, and the limits on funnels and dashboards. Every key.

When a client connects, the server also sends instructions that tell the assistant to call get_project first and how to read the numbers honestly. For an OAuth connection they also name the projects it covers.

Setup runs

A setup run groups the changes an assistant makes, so they undo in one step. Every change made through a write tool belongs to one.

  • Start one with start_setup_run and pass its run_id to every write. A write without run_id starts a run of kind chat and returns its id with run_started: true. A write that fails removes the run it started.
  • Over the REST API the same thing is the header X-Setup-Run-ID on any write to feature rules, funnels, dashboards, widgets or click problems. Writes without it are not recorded and cannot be undone this way.
  • undo_setup_run defaults to dry_run: true, which reports what would happen and changes nothing. The real undo works newest first in one transaction: it removes what the run created, puts back what it changed, and recreates what it deleted with its original id. Anything someone else changed since is skipped and reported. A run can be undone once, and after that it takes no more changes. In the dashboard, the same undo is on the AI assistant changes page.
  • A funnel’s counted days cannot be restored. The undo reports them as funnel_history and funnel_days_lost before and after.
  • A click problem the run resolved or ignored is open again after the undo, and one the run reopened, or switched between resolved and ignored, is put back as it was. If someone resolved, ignored or reopened it since, the undo leaves it alone and reports it.
  • Plan limits apply to writes and to undo alike. get_project returns slots_left for feature rules, funnels, dashboards and widgets.

Keys in your assistant’s settings

These settings apply to assistants connected with an API key. A connection made by signing in covers every project the user allowed and needs none of this. Each key belongs to one project, so an assistant should use the key of the project whose code it works on.

  • Claude Code saves the connection for the folder you run claude mcp add in. Run it in each project’s folder with that project’s key.
  • Cursor reads .cursor/mcp.json from each project’s folder, so each project has its own file and key.
  • Codex uses one connection in every folder unless a project names its own. Pick a variable name for each project, such as PRIVATRAK_API_KEY_SHOP, and save that project’s key under it as for PRIVATRAK_API_KEY. Then create .codex/config.toml in the project’s folder:
[mcp_servers.privatrak]
url = "https://api.privatrak.com/mcp"
bearer_token_env_var = "PRIVATRAK_API_KEY_SHOP"

The file names the variable, not the key, so it can go into your code repository. Codex reads it only in a folder you trust, and asks you about that the first time you start it there.

Switching keys

An assistant registers Privatrak under the name privatrak, so it holds one key at a time. To switch between an AI assistant key and a full access key, replace the old key rather than adding a second one. In Claude Code, run claude mcp remove privatrak in the project’s folder and then the new command. In Codex, change the key in the line that saves it. In Cursor, replace the key in mcp.json.

To sign in instead of using a key, first remove the connection that uses the key: claude mcp remove privatrak in Claude Code, codex mcp remove privatrak in Codex. In Cursor, replace the privatrak entry in mcp.json with the one from Connect an AI assistant. Then sign in as described there, and revoke the old key on the API Keys page.

MCP reference: the Privatrak analytics MCP server