PostHog offers a range of controls to help you manage data collection. This guide covers data collection controls available to you before data reaches PostHog servers.
You should consider the following tools to help you manage data collection:
Feature | Description |
---|---|
Asking for opt out | A top-level opt out of all data collection |
Autocapture behavior | Configure what elements and interactions are automatically captured |
Masking sensitive information | Prevent specific sensitive data from being collected |
Overriding captured events | Modify or filter event data before it's sent to PostHog |
Cookieless tracking | Track users without using browser cookies |
Identifying users | Set up user identification and manage user properties |
If you require that certain data never reaches PostHog servers, you can use one of the tools below to prevent data from being captured.
Asking for opt out
Before capturing data, you may need to ask your users for consent. PostHog provides a top level switch to control data collection.
Opting out on a PostHog client will prevent all data from being captured and sent to PostHog. This includes any autocaptures, manual captures, and session replays.
Opting in and out
You can opt out the current device by calling posthog.opt_out_capturing()
.
posthog.opt_out_capturing()
Similarly, you can opt users in:
posthog.opt_in_capturing()
Checking if a user is opted out
You can check if a user is opted out by calling posthog.has_opted_out_capturing()
.
posthog.has_opted_out_capturing()
Opt out preference persistence
Opting out status is persisted automatically using:
- local storage or cookies for browsers
- shared preferences for Android
posthog.optOut
file in your app's support directory for iOS.posthog-rn.json
for React Native
For browsers, you can control how long the opt out state is persisted by setting opt_out_capturing_persistence_type
to either local_storage
or cookies
.
posthog.init('<ph_project_api_key>', {opt_out_capturing_persistence_type: 'local_storage',});
To persist opt out across sessions and devices, you can save your user's opt out preferences in your app logic. On launch, you can check if the user has opted out and set the opt out state accordingly.
Opting out by default
To opt users out by default, set opt_out_capturing_by_default
to true
in the init
call.
posthog.init('<ph_project_api_key>', {opt_out_capturing_by_default: true,});
Autocapture
PostHog has powerful autocapture features that capture data automatically on the client side. Autocapture is available for Web, iOS, and React Native, and is used by product analytics, web vitals, and heatmaps.
Project level autocapture controls
You can control autocapture behavior at the project level in Settings > Project > Autocapture & heatmaps.
Session level autocapture controls
You can also control autocapture behavior programmatically on the client side.
In web apps using the JavaScript Web SDK, the following data can be autocaptured.
Feature | Data captured |
---|---|
Product analytics | Pageviews, pageleaves, clicks, changes of inputs, and form submissions associated with <a> , <button> , <form> , <input> , <select> , <textarea> , and <label> tags |
Web analytics | Pageviews, pageleaves, conversions, and web vitals |
Session replay | Clicks, mouse movements, scrolling, and snapshots of the DOM |
Error tracking | Exceptions thrown in the browser using onError and onUnhandledRejection |
You can control autocapture using the autocapture
option in the posthog.init
call.
You can disable autocapture entirely by setting autocapture
to false
.
posthog.init('<ph_project_api_key>', {api_host: 'https://us.i.posthog.com',autocapture: false,})
You can also control what is captured using the AutocaptureConfig
object.
posthog.init('<ph_project_api_key>', {api_host: 'https://us.i.posthog.com',autocapture: {dom_event_allowlist: ['click'], // DOM events from this list ['click', 'change', 'submit']url_allowlist: ['posthog.com./docs/.*'], // strings or RegExps// url_ignorelist can be used on its own, or combined with url_allowlist to further filter which URLs are capturedurl_ignorelist: ['posthog.com./docs/.*/secret-section/.*'], // strings or RegExpselement_allowlist: ['button'], // DOM elements from this list ['a', 'button', 'form', 'input', 'select', 'textarea', 'label']css_selector_allowlist: ['[ph-autocapture]'], // List of CSS selectorselement_attribute_ignorelist:['data-attr-pii="email"'], // List of element attributes to ignore},})
Hide sensitive information with autocapture
You can also mask individual elements of the view hierarchy from being captured.
PostHog will make a best effort to not capture sensitive information by default. This is not always sufficient, so you can disable autocapture for specific elements.
By default, PostHog only collects the name
, id
, and class
attributes from <input>
tags.
If there are other HTML elements you don't want captured, you can add the ph-no-capture
class to the element.
<button class='ph-no-capture'>Sensitive information here</button>
Masking sensitive information
You can safely capture session replays events without compromising your users' privacy. PostHog offers a range of masking techniques that let you mask over sensitive information.
The following masking techniques are available:
- Masking inputs: Mask out sensitive inputs from being captured. Individual inputs can be unmasked.
- Masking text elements: Mask out sensitive text from being captured. Individual text elements can be unmasked.
- Masking other elements: Mask out any individual element from being captured.
- Redacting information on network captures: Redact sensitive information from network captures.
Private by default
If you have data that should never be captured, a safe way to start with PostHog is to mask all inputs and text, only selectively unmasking elements that you need to capture.
You can set specific data attributes on elements to control whether they are captured or not:
{// mask all inputs by defaultmaskAllInputs: true,maskTextSelector: "*",maskTextFn: (text, element) => {// only elements with `data-capture="true"` will be capturedif (element?.dataset['capture'] === 'true') {return text}return '*'.repeat(text.trim().length)},}
Selectively unmasking elements is not currently available for mobile session replay. You should be more selective about which screens you capture, and take care to mask out sensitive information.
Masking all inputs and text by default in session replay ensures that data is only captured when explicitly unmasked, putting you in control of what's captured.
Overriding captured events
Before an event is sent to PostHog, you have a final chance to modify it to remove sensitive information. You can do this by using the before_send
hook. This hook is only available for the JavaScript Web SDK.
posthog.init('<ph_project_api_key>', {api_host: 'https://us.i.posthog.com', // usually 'https://us.i.posthog.com' or 'https://eu.i.posthog.com'capture_pageview: 'history_change',before_send: function(event) {if (event.properties['$current_url']) {event.properties['$current_url'] = null;}return event;},})
Cookieless tracking
For PostHog to work optimally, we store a small amount of information about the user on the user's browser. This ensures we identify users properly if they navigate away from your site and come back later.
The information we store includes:
- Their
distinct_id
- Session ID & Device ID
- Active & enabled feature flags
- Any super properties you have defined
- Some PostHog configuration options (e.g. whether session recording is enabled)
By default, we store all this information in both a cookie
and localStorage
, which means PostHog can identify your users across subdomains. By default, the name of the cookie PostHog sets is ph_<project_api_key>_posthog
and it expires after 365
days.
You can update the persistence of the PostHog client according to your user's cookie consent or your compliance requirements.
persistence: "localStorage+cookie"
(default): Limited things are stored in the cookie such as the distinctID and the sessionID, and everything else in the browser's localStorage.persistence: "cookie"
: Stores all data in a cookie.persistence: "localStorage"
: Stores everything inlocalStorage
.persistence: "sessionStorage"
: Stores everything insessionStorage
.persistence: "memory"
: Stores everything in page memory, which means data is only persisted for the duration of the page view.
const handleCookieConsent = (consent) => {posthog.set_config({ persistence: consent === 'yes' ? 'localStorage+cookie' : 'memory' });localStorage.setItem('cookie_consent', consent);};
Using persistence: "memory"
helps comply with cookie and consent requirements. This does not affect what data is captured and stored by PostHog.
You still need to configure data collection and storage separately to comply with relevant regulations.
The JavaScript Web SDK has a more detailed guide on managing persistence and cookies.
Identifying users
To track users across sessions and devices, PostHog needs to identify them. This is done by calling posthog.identify()
.
Some features depend on cohorts to work well. Some information beyond a basic distinct_id
is required to use these features:
- Feature flags - target specific user segments in experiments
- Surveys - Enable for specific cohorts of users
- Insights - filter and breakdown by user characteristics
posthog.identify('distinct_id', // Replace 'distinct_id' with your user's unique identifier{ email: 'max@hedgehogmail.com', name: 'Max Hedgehog' } // optional: set additional person properties);
Information you pass to posthog.identify()
will be sent to PostHog servers. Depending on your compliance requirements, you may not be able to store some of this information.
If you plan to use these features, consider how you can identify these groups of users without breaking compliance requirements.