On-chain vs Off-chain
AdPriva keeps its records off-chain and puts only one hash per batch on-chain. This page lists what lives where.
Off-chain: AdPriva’s database
- Every proof and consent certificate, with its seal, score and verdict.
- The data captured with each proof: aggregate interaction counts, page path, referrer, IP address and user agent. The raw IP address and user agent are emptied after 30 days (current production setting).
- The batches, their Merkle roots and each proof’s place in its batch.
This is where sealing and scoring happen, in real time, when an event arrives. The public API and the Explorer read from here, and show no publisher, site, page or visitor data.
zkVerify: retired
New batches are not sent to zkVerify. For view batches anchored before 2026-09-28, the anchor worker sent zkVerify a Groth16 zero-knowledge proof with the batch’s Merkle root as its only public input. Those attestations stay on zkVerify’s chain as legacy records. See Legacy: zero-knowledge step.
Consent batches never had this step.
On-chain: Horizen
- Each batch’s Merkle root is sent to AdPriva’s
Anchor.solcontract on Horizen, which emits anAnchored(merkleRoot)event. - The contract stores nothing else. The event is the permanent public record.
- One transaction per batch, whatever the batch size. Batches are made every 5 minutes, or sooner when 100 proofs are waiting.
Comparison
| Off-chain (AdPriva database) | On-chain (Horizen) | |
|---|---|---|
| What is there | Full records: proofs, verdicts, consent certificates | One Merkle root per batch |
| When | As each event arrives | When each batch is anchored |
| Personal data | Yes, with the retention described in Data Flows for your DPIA | None: only hashes |
| Who can read it | Public lookup by proof id (no publisher, site or visitor data); full records only for the owning organization in the console | Anyone |
| Can it change | AdPriva runs the database | No: the transaction is permanent |
Checking one against the other
A proof’s Merkle inclusion receipt, from GET https://api.adpriva.com/public/proofs/{proof_id}, lets you recompute its batch root offline and compare it with the Anchored event. That shows the proof was in the batch when the batch was anchored. It does not fix the proof’s score or verdict, which live only off-chain. See Proof Systems & Verification.
{% @mermaid/diagram content="flowchart TD
A\[View event]
B\[Ingest server: seal and score]
C\[AdPriva database: full records]
D\[Anchor worker: Merkle batch]
E\[Horizen: Anchored event]
F\[Public API and Explorer]
A --> B
B --> C
C --> D
D --> E
C --> F" %}