Delete user data (GDPR, CCPA)

Erase a person from Ripples on a GDPR or CCPA request with one API call, and reset or opt out the browser with the JS SDK.

Under GDPR you are the controller of the data you collect about your users, and Ripples processes it for you. When one of them asks to be forgotten, you answer the request. The API below is how you remove everything Ripples holds about them, from the same backend that deletes their account.

What gets deleted

One request erases the whole person, not just the id you sent. Ripples follows its identity graph first: every device the person used, every anonymous session that was later linked to their account, and the events your server sent for them.

DataWhen it is gone
The person’s profile: name, email, avatar, plan, custom traits, first touch, location, devicesAbout a minute
Their subscriptions (MRR records) and app install attributionsAbout a minute
Their events: pageviews, product usage, signups, payments, identifiesThe nightly run, within 24 hours
Their sessions, Web Vitals samples and filtered bot hitsThe nightly run, within 24 hours
Them in daily totals (visitors, signups, payers)Rebuilt from the cleaned events after the nightly run

What stays:

  • Totals with nobody in them. Saved MRR history and traffic-quality counts are numbers per day with no identifier inside, so they are not personal data and are kept.
  • The deletion request itself. The ids you sent and the dates the request was carried out are kept as your record that you handled it.

Past reports change. A deleted person's visits, signup and payments leave every report, so earlier days can show a little less traffic, fewer signups or less revenue than before. That is the point of an erasure.

Delete a person

Send the ids you know for the person. Use your secret key (Settings → Integrations → Project secret key). A publishable project token is refused, because it sits in every page of your site.

curl -X POST https://api.ripples.sh/v1/privacy/deletions \
  -H "Authorization: Bearer priv_XXXX" \
  -H "Content-Type: application/json" \
  -d '{
    "user_ids": ["4812"],
    "emails": ["[email protected]"],
    "requester": "[email protected]"
  }'
Parameter Type Description
user_ids optional string[] The ids you pass to identify() and signup(). The best handle: it reaches every device the person signed in on.
visitor_ids optional string[] Device ids (UUIDs) from ripples.getVisitorId(). Use these for someone who never signed in. If the device belongs to a signed-in person, that whole person is deleted.
emails optional string[] Matched against profile emails, ignoring case. Useful when the request names only an address, for example a Stripe customer who never signed in.
requester optional string Free text for your own records, such as who asked or a ticket number.

Send at least one id and at most 100 ids in total per request. To delete more people, send more requests.

The response is 202 with the request:

{
  "id": "9d2c6f0e-8a41-4f7b-b1f2-6c3e5a7d9b10",
  "status": "pending",
  "user_ids": ["4812"],
  "visitor_ids": [],
  "emails": ["[email protected]"],
  "requester": "[email protected]",
  "profiles_deleted": null,
  "created_at": "2026-10-01T14:03:11Z",
  "profiles_deleted_at": null,
  "completed_at": null
}

Keep the id if you want to show later that the request was completed.

Shared devices

A visitor id reaches two things: the person who last signed in on that device, and the device’s anonymous activity (everything recorded while nobody was signed in). Activity recorded under a different user id is never deleted through it. Two people who share a laptop, or someone who deletes their account and signs up again on the same phone, keep their own data.

Check progress

curl https://api.ripples.sh/v1/privacy/deletions/9d2c6f0e-8a41-4f7b-b1f2-6c3e5a7d9b10 \
  -H "Authorization: Bearer priv_XXXX"
statusMeaning
pendingAccepted. The profile is about to be erased.
processingProfile, subscriptions and caches are erased (profiles_deleted says how many profile records). Events are waiting for the nightly run.
completedEverything listed in What gets deleted is gone. completed_at is the time.

To list recent requests, newest first:

curl "https://api.ripples.sh/v1/privacy/deletions?status=processing&limit=50" \
  -H "Authorization: Bearer priv_XXXX"

This returns {"data": [ ... ]} with the same objects. limit defaults to 50, maximum 100.

In the browser

The API erases what Ripples stored. The tracking script also keeps a device id in the browser, in the _rpl_vid cookie and localStorage. Three calls control it (tracker v1.6.0 and later).

On logout: ripples.reset()

ripples.reset()

Forgets the signed-in user and starts the browser over as a new anonymous visitor with a new session. Call it when someone logs out, so whoever uses the browser next is not linked to them. Tracking carries on as normal. It is the same as posthog.reset() or Amplitude’s reset().

When someone asks not to be tracked: ripples.optOut()

ripples.optOut()

Deletes every Ripples cookie and storage entry in this browser (the device id, the session, the stored user id) and stops the script sending anything, on this page and on every later visit. The only thing kept is a _rpl_optout=1 flag, so that the choice is remembered. Call it when a user deletes their account, or from a cookie banner when consent is refused.

ripples.optIn()        // undo: tracking resumes as a new visitor
ripples.hasOptedOut()  // true or false

optIn() counts the current page, because its load was not recorded while the browser was opted out. While opted out, ripples.getVisitorId() returns an empty string.

optOut() does not delete anything on the server. It only cleans the browser. To remove what Ripples already holds, call the deletion API from your backend with the user's id, and send the device id from ripples.getVisitorId() before calling optOut() if the person never signed in.

After the deletion

Deleting a person does not block them. If your app or server keeps sending events with their user id or device id, Ripples records a new person. When a user deletes their account:

  1. Delete their account in your app.
  2. Call the deletion API with their user id from your backend.
  3. Call ripples.optOut() in their browser, or ripples.reset() if they may keep using the site anonymously.
  4. Stop sending server events for that user id.

Payment integrations follow the same rule. If Stripe or Paddle later sends a payment for the same customer (a refund, a final invoice), Ripples records it as a new person. Remove them from your billing provider too if the erasure covers it.

Errors

StatusWhen
401Missing or unknown key.
403A publishable project token was used. Use the priv_ secret key.
404No deletion request with that id in this project.
422No ids, more than 100 ids, a visitor id that is not a UUID, or an invalid email. The body says which field: {"error": "...", "errors": {...}}.
429More than 200 requests a minute from one IP address.

FAQ

Can I cancel a deletion? No. The profile is erased within about a minute, so there is nothing left to cancel. Check the ids before sending.

Does it delete the person in every project? No. A secret key belongs to one project, and the request only reaches that project. If you track the same users in several projects, send a request with each project’s key.

The person was never identified. How do I find them? Send their device id. Read it with ripples.getVisitorId() in their browser, for example on your privacy request form, and send it along with the request.

Is the deletion request itself personal data? It holds the ids you sent and nothing else. Ripples keeps it as your proof that the request was carried out.