Privacy Policy
PDFVault opens, annotates, fills and signs PDFs entirely inside your browser. Your documents are never uploaded anywhere — not to us, not to anyone. There is no server that has ever seen one of your files, because there is no upload path in the code at all.
We do collect a small amount of anonymous product-usage measurement:
which built-in tools got used, and coarse “how many”-style buckets like
2-5. That’s it. It is tied to a random identifier generated on your
own device that is never connected to your name, email, or payment details. You
can switch it off in Settings at any time.
What we collect
Only two things ever leave your device, and only one of them is about you:
- Anonymous product-usage events (described exhaustively below), if you have not turned them off.
- The licence key, if you upgrade — sent to our payment provider so it can confirm the purchase is valid. See Payments.
The exact shape of what is sent
Events are buffered locally and sent in the background as a batch. A complete request body looks like this — there is no other field, ever:
{
"v": 1,
"install_id": "b3f9c1a4-5e2d-4c77-9a10-2f8e6d0b7c33",
"events": [
{ "name": "tool_used", "ts": 1754476800000, "props": { "tool": "pen" } },
{ "name": "export_completed", "ts": 1754476912000, "props": { "element_count": "2-5" } }
]
}
install_id— a random UUID generated on your device. It is not derived from anything about you, your computer, your browser or your documents. It is never linked to a name, email address or payment record. Reinstalling produces a brand-new, unrelated id.name— one value from the closed list below. A name that isn’t on the list is discarded before any network payload is built.ts— a timestamp from your device’s clock.props— key/value pairs where both the key and the value must appear in the allowlist below. Anything else is dropped whole, not “cleaned up”.
Every event we can send
This is the complete vocabulary. There are no others, and the extension is built so an event outside this list cannot be transmitted even by mistake.
| Event | Fires when | Properties |
|---|---|---|
extension_installed | Once, on install (not on updates) | — |
viewer_opened | The viewer tab is opened | — |
pdf_loaded | A PDF is opened | page_count (bucket) |
tool_used | You switch tools in the toolbar | tool |
text_committed | You finish adding or editing text | — |
signature_placed | You place a signature | — |
form_field_filled | You fill a form field | field_count (bucket) |
export_completed | An export finishes | element_count (bucket) |
more_menu_opened | The “More” menu is opened | — |
settings_opened | Settings is opened | — |
pro_tool_clicked | You click a Pro feature | pro_tool, source |
upgrade_page_opened | The upgrade page is opened | pro_tool, source |
merge_run | A merge finishes | — |
ocr_run | An OCR pass finishes | — |
upgrade_completed | Once, when an install goes free → paid | — |
Every property value we can send
| Key | The complete set of values it may ever have |
|---|---|
tool | none, select, pen, highlight, rect, text, signature |
pro_tool | merge, ocr |
source | toolbar, more_menu, empty_state, settings, upgrade_sheet |
page_count | 0, 1, 2-5, 6-20, 21-100, 100+ |
element_count | same buckets |
field_count | same buckets |
Those bucket labels are the whole point: we never learn that your document
has 37 pages, only that it is in the 21-100 band. An exact
count is a fingerprint of a specific document, so exact counts are structurally
impossible to send — the allowlist rejects raw numbers outright.
What we never collect
Concretely, and not as an aspiration — these are things the code cannot transmit:
- The contents of your documents. No page text, no extracted text, no OCR output.
- File names. Ever. Not truncated, not hashed.
- Form field names or values. Filling a form sends a bucket like
2-5. Not which field. Not what you typed. - Signature images. Placing one sends the fact that it happened. The image never leaves your device.
- Page thumbnails, screenshots, or any rendering of your pages.
- Exact counts of anything. Coarse buckets only.
- IP addresses at rest. Our server sees the source IP of an incoming request, as every HTTP server does. It is held in memory only, used solely to rate-limit abuse, and is never written to storage.
- Location. No GPS, no geolocation API, no stored IP-derived location.
- Cross-device or cross-account identity. There is no login, no account, no sync. Your ids on two machines are unrelated random values and we cannot connect them.
- Browsing history or the URLs of pages you visit. The extension requests no host permissions at install and has no content scripts — it does not run on websites, only on its own page. If you use the right-click “Open in PDFVault” entry point, Chrome asks your permission at that moment and the address of that one document is read locally so the file can be opened. It is never transmitted to us, and no property in the allowlist above can even hold a URL.
- Anything outside the vocabulary above. An unrecognised event or property is discarded before a request is constructed.
We also do not use cookies, fingerprinting, ad networks, third-party analytics SDKs, session recording, or cross-site tracking of any kind. We do not sell your data and we do not share it. There is no “anonymised data partner”, no data broker, no affiliate.
Where the data goes and who can see it
The measurement data goes to a first-party collector we run ourselves:
- An AWS Lambda Function URL writing to an Amazon S3 bucket, both inside our own AWS account.
- Region:
eu-central-1(Frankfurt, European Union). Data is stored in the EU. - There is no third-party analytics vendor in the path. No Google Analytics, no PostHog, no Mixpanel, no Amplitude, no Segment, no pixel, no tag manager.
Who can see it: the operator of PDFVault, and AWS in its capacity as infrastructure provider. Nobody else. We would disclose it only if legally compelled — and what we hold is an anonymous install id plus event names, which identifies no one.
Verifying this yourself
You do not have to take our word for any of it:
- Watch the traffic. The request is made by the background service worker, not the
viewer tab, so DevTools on the tab will not show it — that is
deliberate (a closing tab is the worst place to start a request). Go to
chrome://extensions, enable Developer mode, click service worker under PDFVault, and watch that inspector’s Network tab. You will see exactly the JSON above, to one host, and nothing else. - The manifest requests
storage,unlimitedStorage,contextMenusandactiveTab— and no host permissions at install. An extension without host permissions cannot read the pages you visit. It also declares one channel that lets our own checkout page pass a licence key to the extension after you upgrade, so you never have to copy and paste one; nothing else can use it.
How long we keep it
- Raw events: 400 days. An S3 lifecycle rule deletes them automatically — expiry is enforced by the storage layer, not by us remembering.
- Data on your own device (your PDFs, annotations, saved signatures, settings and your Recent files list) stays until you delete it. It lives in your browser’s IndexedDB. Removing the extension removes it, and Clear list empties Recent files at any time. We never had a copy.
How to turn it off
Open Settings in the viewer and switch the analytics toggle off.
- Measurement is on by default, and the extension says so in-product with the toggle right there.
- Turning it off stops collection immediately.
- It also deletes anything still buffered on your device, so a later background send has nothing to ship. “Off” means off, retroactively, for anything unsent.
- The setting is remembered.
One honest limitation, stated because it is the kind of thing a privacy policy usually hides: because an opted-out install sends nothing at all, we cannot measure how many people opt out. We would rather report “unknown” than invent a number.
Payments
Paid upgrades are handled by a third-party payment provider acting as the merchant of record. Whichever provider we use, these hold:
- Your card details are entered on their checkout, never inside PDFVault and never on a form we operate. We never see, receive or store a card number, billing address or any payment credential.
- The only thing the extension learns is, in effect, a yes or no: whether this install is entitled to the paid features. That is what unlocks them.
- The payment system and our measurement system are deliberately
unlinked. Your random
install_idis never sent to the payment provider, and the email or payment identity you give them is never sent to us. We cannot join the two, by construction. - The only thing our measurement records about payment is a single anonymous
upgrade_completedevent — that some install went paid, and roughly when. No amount, no currency, no transaction id, no name, no email. - The provider handles the data you give it under its own privacy policy; for that transaction they are the data controller, not us. Their identity is named on the checkout page before you enter anything.
Children
PDFVault is a general-purpose document tool. It is not directed at children, and we do not knowingly collect personal information from anyone of any age — there is no field in what we collect that could identify a child or an adult.
Changes
If this policy changes we will update the date at the top and publish the new version at this same URL. Material changes — anything that widens what we collect — will also be called out in the Chrome Web Store listing and, where the change affects what leaves your device, in the extension itself. We will not start collecting a new category of data under an old policy.
Contact
Questions, complaints, or a request to delete data associated with your install id: privacy@pdf-vault.co
To have your install’s events deleted, send us your install id. Because the id is
deliberately not shown anywhere in the interface, you can read it with DevTools on
the PDFVault tab: Application → Storage → IndexedDB → pdfvault
→ meta → installId. If you would rather not send
it, just turn the toggle off and uninstall — the id exists only on your device, and
any events already received expire within 400 days regardless.