The pilot is full.
All pilot spots are taken. We're onboarding new customers on a rolling basis — leave your email and we'll reach out when there's room.
Prices are hidden while we run the pilot. Here is how the plans are shaped:
| Plan | For | What you get |
|---|---|---|
| Hobby | Personal projects and small sites | Analytics and ads for a few sites at modest volume. The same privacy by design as every other plan. |
| Startup | Growing products with several sites | Higher volume and more sites, with multi-URL tokens and a per-origin breakdown in the dashboard. |
| Enterprise | Large volumes and compliance needs | Custom volume, a signed DPA and direct support. Talk to us about your requirements. |
Pricing is shared with pilot customers directly and will be published when the pilot ends.
Uptime
We target 99.99% uptime. MVSP runs entirely on Google Cloud (Cloud Run, Firestore, BigQuery and Firebase Hosting) with no other infrastructure in the request path, so availability depends only on Google.
Ship it in thirty seconds.
Drop this snippet into the <head> of your site.
Replace YOUR_SITE_TOKEN with the token we issued you.
<script src="https://api.mvsp.ai/releases/analytics.6cbf401dd2415fcf.js"
integrity="sha384-bL9AHdJBX898nqDPhIB4jZfc6CfsDoVxBbO8kR8tRx+oXtNM1Vo7anQk2zNZJa7P"
crossorigin="anonymous"
data-site-token="YOUR_SITE_TOKEN"
data-api="https://api.mvsp.ai"></script>
Pinned by design. The snippet carries a
Subresource Integrity hash (integrity) and points at an
immutable, versioned file. Your browser refuses to run anything that
is not byte-identical to what we released, so nobody can change the
script on your site, even if they were to gain control of the domain.
Released files never change; new versions get a new URL and hash.
Current hashes are also listed in
/releases/manifest.json.
The script starts tracking pageviews and session duration immediately.
No cookies are set, and no direct
identifiers (name, email, user id) are ever collected — only
anonymised IP, user agent, referrer and page path are stored, for 365
days. The script also honours the browser's
Do Not Track and Global Privacy Control
signals: if either is set, nothing is sent. Whether you still need a
consent banner is your call as the site operator — the analytics data
itself is anonymous under the EDPB's cookie-guidance criteria, but any
personally identifying values you place in
customParams obviously carry their own obligations.
Track anything you can name.
Once the script has loaded, call window.mvspAnalytics:
// Simple event mvspAnalytics.trackEvent('button_click'); // With metadata mvspAnalytics.trackEvent('purchase', { eventCategory: 'transaction', eventLabel: 'premium_plan', eventValue: 299, customParams: { plan: 'yearly', currency: 'USD' } }); // GDPR right-to-erasure — deletes this visitor's rows and clears local state. mvspAnalytics.erase();
No identity API. There is deliberately no
setUserId() — MVSP Analytics does not accept persistent
user identifiers from the site you embed it on.
Send events straight from your backend.
Node, Python, curl, whatever — hit the API directly:
# Pageview curl -X POST https://api.mvsp.ai/analytics/pageview \ -H "Authorization: Bearer YOUR_SITE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"pagePath":"/product/42","pageTitle":"Widget"}' # Event curl -X POST https://api.mvsp.ai/analytics/event \ -H "Authorization: Bearer YOUR_SITE_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "eventName": "signup", "eventCategory": "conversion", "eventValue": 1 }'
Serve your own banners, count every click.
Upload a JPG (or just a headline and some text), pick a category and tick the sites that should show it. Banners rotate at random by weight, and impressions and clicks are counted per banner and site — still without cookies.
<div data-mvsp-ad></div>
<script async src="https://api.mvsp.ai/releases/embed.deb6d26fa572279a.js"
integrity="sha384-3rbSb6VyJ5pxen9z886pL/LWX4aX4Humer2kvK6G+QC1Uf1Bexq2cIWCAxI9IyNN"
crossorigin="anonymous"
data-site="YOUR_SITE_SLUG"></script>
Slots, categories and the JSON API are covered in the ads guide.
The whole surface, on one page.
| Endpoint | Description |
|---|---|
POST
/analytics/pageview
|
Record a pageview |
POST
/analytics/event
|
Record a custom event |
GET /analytics.js
|
Client script |
GET /ads/embed.js
|
Banner embed script |
GET /ads/serve
|
Pick active ad(s) for ?site=, optional
category, limit
|
GET
/ads/click/:id
|
Count a click, then redirect to the advertiser |
GET /ads/info
|
Ads guide |
POST
/privacy/erase-session
|
GDPR right-to-erasure — queue deletion of all rows for a
sessionId
|
GET /health |
Sanity check |
One kind of token, one purpose.
| Type | Where it lives | What it can do |
|---|---|---|
Site tokenmvsp_pk_… |
In your HTML — public | Only write events and pageviews for a single site |
allow_all:true accept requests
from any domain — perfect if you own multiple sites and want to reuse
a single token across all of them, then view the per-origin
breakdown in the dashboard. Otherwise
allowed_origins must be set explicitly and only matching
origins are accepted.
Actionable numbers, no individual tracking.
MVSP is built to be unable to identify users. Results are aggregated and anonymised at collection time, not just in the dashboard. Everything below applies by default — nothing to configure.
There is no user identity to recover: no login, name, email, cookies or persistent user ID, only a random per-visit session ID that cannot be linked to a person. IP addresses are truncated before storage, location is country-level only, and the reports you get are totals, top lists and time series, never profiles of individual visitors.
What we collect per event
| Field | Purpose | Personal data? |
|---|---|---|
session_id |
Aggregate pageviews from the same visit |
Random UUID, not linkable to identity, stored in
localStorage only
|
ip_address |
Rough visit counting and abuse detection |
Anonymised before storage — last octet of IPv4
zeroed (1.2.3.42 -> 1.2.3.0), last 80 bits of IPv6
zeroed. Raw IP never touches disk and there is no server-side
setting to disable anonymisation.
|
user_agent |
Browser and OS breakdown | Low entropy on its own |
referrer, origin |
Attribution & multi-site breakdown | URLs of the referring page and the site the event came from |
country |
Country-level breakdown |
ISO-3166 alpha-2 code, read strictly from CDN / load-balancer
headers (Cloudflare, Google Cloud, Fastly). If no header is
present, the field is NULL — we do not run any
geo-IP lookup on the raw IP address.
|
page_path, page_title,
event_*
|
The actual analytics data you asked for |
Whatever you send us — do not put personal data in
customParams
|
What we do not collect
-
No cookies. Session ID lives in
localStorage, tied to the browser, and cleared when the visitor clears storage or callsmvspAnalytics.erase(). -
No persistent user identifiers. There is no
setUserId(), nouser_idcolumn, no login-linking API. If you need per-user analytics, this is not the tool for you. - No cross-site tracking. Each site's data is isolated by site token — one site cannot read another's events.
- No fingerprinting. We don't hash user agent + IP, don't use canvas or WebGL probes, don't measure fonts.
- No third-party ad networks or trackers. Data goes only from the visitor's browser to our servers. Static assets (fonts, styles) are self-hosted; no Google Fonts, no CDN pings.
-
DNT and GPC are honoured. If the browser sends
Do Not Track: 1orSec-GPC: 1, the script sends nothing at all.
Retention
All rows are partitioned by day. Partitions older than 365 days are automatically deleted by BigQuery. There is no soft-delete: after that window the data is physically gone.
Where the data lives
Google Cloud Platform, EU multi-region — BigQuery EU,
Firestore eur3, Cloud Run europe-north1
(Finland). No data leaves the EU.
Sub-processors
Per GDPR art. 28(2), the complete list of sub-processors we rely on to run this service:
| Provider | Purpose | Region |
|---|---|---|
| Google Cloud (Google Ireland Ltd.) | BigQuery, Firestore, Cloud Run, Cloud Logging | EU (europe-north1 / eur3 / EU multi-region) |
| Google Cloud Scheduler (Google Ireland Ltd.) | Daily invocation of the erasure-queue drain (no personal data transits Scheduler — it only sends an authenticated HTTP call) | europe-west1 (Belgium) |
| Firebase Hosting (Google Ireland Ltd.) | Static asset delivery, TLS termination | Global CDN, EU-origin |
We will announce new sub-processors here at least 30 days before they start processing personal data, per art. 28(2).
Data subject rights
Because we don't store any direct identifiers, most GDPR requests fall away by construction. The rights we can still service:
-
Erasure (art. 17): anyone can trigger deletion of
their own rows without contacting us. From the browser:
mvspAnalytics.erase(). Or POST the session id directly:
curl -X POST https://api.mvsp.ai/privacy/erase-session -H "Content-Type: application/json" -d '{"sessionId":"…"}'
The request is queued (BigQuery has a ~90-minute streaming buffer during which DML can't touch new rows) and completed well within the 30-day GDPR window. -
Access & portability (art. 15/20): no need to
contact us. From the browser:
mvspAnalytics.exportData(). Or POST the session id directly:
curl -X POST https://api.mvsp.ai/privacy/access-session -H "Content-Type: application/json" -d '{"sessionId":"…"}'
The response is JSON with all pageview and event rows for that session.
Records & contracts
- Register of processing activities (GDPR art. 30)
- Standard data processing agreement (GDPR art. 28) — sign electronically or send us a counter-signed copy
- Sub-processor register
For your privacy policy
mvspAnalytics.erase() in your
browser console.
Ads
Privacy questions: privacy@mvsp.ai