GDPR & consent

userGist is built for products that ship to GDPR/CCPA-regulated users. Consent is a first-class input — without it, no events queue, no surveys render, no pushes send.

The SDK accepts a Consent object with four independent boolean purposes:

PurposeGates
analyticsBehavioural events (track, lifecycle events).
feedbackOne-question prompts.
pushPush token registration and delivery.
surveyMulti-step surveys.

If a purpose is false, the corresponding subsystem is gated client-side: events stay un-queued, prompts don't render, push tokens aren't registered.

  1. 1

    Init the SDK with all purposes off (or your existing stored consent)

    UserGist.init({ writeKey: 'rk_live_...', environment: 'production' })
    await UserGist.setConsent({
      analytics: false,
      feedback: false,
      push: false,
      survey: false,
    })
  2. 2

    Show your consent UI

    Use your existing CMP or build a simple in-app screen with toggles per purpose.

  3. 3

    Persist + apply the user's choice

    Save it locally (so you don't show the banner twice) and tell the SDK:

    await UserGist.setConsent({
      analytics: true,
      feedback: true,
      push: false,
      survey: true,
    })
  4. 4

    Allow re-opening

    Provide a Privacy preferences button somewhere (settings screen, footer) so users can change their mind. Wire it to the same setConsent call.

  • track() calls are accepted by the SDK but not queued or sent.
  • Targeted prompts and surveys won't render even if a trigger fires.
  • Push registration and delivery are gated. When consent is withdrawn, also call the SDK's disablePush() method so the current device token is invalidated at UserGist and notification permission handling stays explicit in your app.
  • Lifecycle events (app_opened, session_started) respect the analytics gate.

PII allow-list

Even with consent, userGist blocks high-sensitivity properties by default:

  • Contact and identity keys such as email, phone, mobile, ssn, tax_id, national_id, passport, names, postal addresses, and birth dates.

If you legitimately need to send one, add its exact property key to the per-app allow-list at App settings → Privacy. Matching properties that are not allow-listed are removed before storage; the rest of the event or identify call is accepted.

Privacy settings in app settings.
App settings → Privacy. Configure the per-app PII allow-list.

Right to be forgotten (deletion)

Two paths:

  • DashboardUsers → search user → Delete user. Queues a deletion job.
  • APIPOST /v1/apps/:appId/gdpr/delete with a signed-in operator's WorkOS access token and admin role. Send either { "externalId": "..." } or { "anonymousId": "..." }.

Deletion:

  1. Resolves all anonymous aliases linked to the subject.
  2. Removes the subject graph, consent, response, engagement, and device-token records.
  3. Redacts authored request content while preserving unrelated users' engagement.
  4. Deletes the matching analytics data before the job is marked complete.

Right of access (export)

Call POST /v1/apps/:appId/gdpr/export with an externalId or anonymousId. The response contains an exportId; poll GET /v1/apps/:appId/gdpr/exports/:exportId until a short-lived download URL is ready. Both endpoints require a signed-in dashboard operator, and creating the export requires the admin role.

Data residency

The default region is EU (Frankfurt). US is available on request for Enterprise plans.

DPA & subprocessors

A signed DPA is available on request. The current subprocessor list (Cloudflare, AWS, Postmark, Paddle, etc.) is published at usergist.com/legal/subprocessors.

What's next

Web initialization is inactive: it does not create a visitor identity, open storage, send requests or mount UI. Apply the intended consent and explicitly identify a participant using a server-minted token. Anonymous participation requires both allowAnonymous and startAnonymous(); see the Web SDK guide.

On web, feedback consent governs feedback, in-app messages and feature requests; survey consent governs surveys. Withdrawing one of these closes its displayed screen and discards its queued work, while other consent purposes remain independent. Browser push is not implemented.

Await reset() on host logout before identifying another account. It ends the browser client, clears its pending work and resets other active tabs for that user. It does not revoke consent or invalidate native push registrations across that user's devices.