If you’re using PostHog to track user behavior and product analytics, it’s essential to filter out internal team members and test accounts to keep your data accurate. In this guide, you’ll learn how to set up PostHog internal user filtering to ensure clean and reliable analytics.

Why You Should Filter Internal Users in PostHog

By default, PostHog captures all events; including those from developers, marketers, QA testers, and anyone on your team. This can skew data and lead to misleading insights. Setting up filters for internal and test users in PostHog helps:

  • Keep your conversion rates accurate
  • Ensure event data reflects real user behavior
  • Avoid false signals in A/B testing

Here’s how to exclude internal users from tracking in PostHog:

Decorative

Did you know?

We can just do things for you!

Contact Us

1. Go to Settings

From the PostHog sidebar, navigate to Settings. Scroll down to find the section called “Filter out internal and test users.”

PostHog internal user filtering step1
Filtering Out Internal and Test Users in PostHog Settings

2. Add Filtering Rules

You can filter users by various properties, such as:

  • IP address (e.g., office IPs or VPNs)
  • Email domain (e.g., @yourcompany.com)
  • Custom user properties
  • URL parameters (for test sessions)
PostHog internal user filtering step2
Adding Filter Rules in PostHog

Example: To exclude specific IPs

  • Property: IP address
  • Operator: does not contain
  • Value: 192.168.1.1, 10.0.0.1 (use commas to separate multiple values)
    Read this article to learn everything you need to know about Filters.

3. Use Multiple Filters if Needed

PostHog supports multiple rules at once, helping you build a comprehensive internal user exclusion filter. Combine filters like IP address + email domain for better accuracy.

4. Apply Globally or Per Insight

You can choose to:

  • Toggle “Enable this filter on all new insights” for global filtering
  • Or manually apply filters on individual reports or dashboards

Adding these filters ensures you’re analyzing clean, trustworthy data. This is especially important when you rely on PostHog for product decisions, marketing performance, or feature testing.

Conclusion

Setting up PostHog internal user filtering is one of the best ways to maintain clean analytics and improve decision-making. Whether you’re launching experiments or measuring product engagement, filtering out your internal team ensures your data reflects real users.

PostHog also has a detailed guide on this topic; you can check it out here.

More Tutorials You Might Like

If you found this guide helpful, check out our other tutorials to level up your analytics game:

PostHog Slack Integration: Send Event Alerts to Slack
Set Up a PostHog Alert for Your Website

Frequently asked qusetions

No. The “Filter out internal and test users” feature works at the analysis level, not the ingestion level:

  • Events from internal users are still captured and stored in PostHog.

  • Filtering simply removes them from the insight or dashboard you’re looking at, so metrics don’t include that traffic.

If you want to stop sending internal data altogether (e.g. to reduce event volume), you need to handle that in your implementation: disable tracking on dev/staging hosts, add config checks, or avoid sending events for internal users.

There are two places involved:

  1. Project settings – define which filters mark a user/session as internal.

    • Go to Project settings → “Filter out internal and test users”.

    • Add your filters there (email domains, IPs, hosts, cohorts, etc.).

  2. Insight-level toggle – actually enable/disable the filter for a specific report.

    • When editing or creating an insight, use the “Filter out internal and test users” toggle in the filters panel.

    • ON = insights exclude traffic matching your internal filters. OFF = all traffic visible.

  • Project-level filters (Settings):
    Define how PostHog recognizes internal/test users (e.g. “email doesn’t contain @mycompany.com”, “host doesn’t equal localhost:3000”). These rules live in Project settings → Filter out internal and test users and are shared across all insights.

  • Insight-level toggle:
    Decides whether those project-level rules are applied to a specific graph, funnel, or dashboard. The toggle simply adds your internal filter group as extra filters whenever it’s turned on.

You can still add normal filters directly on an insight (e.g. “country = US”) even when the internal user filter is off.

You have two main options:

  1. Using the internal user settings (recommended for analysis):

    • Go to Project settings → “Filter out internal and test users”.

    • Add a filter on your IP-related property (e.g. IP, ip, or a custom office_ip property if you set one).

    • Use an operation such as “doesn’t equal” or “doesn’t contain” with a comma-separated list of internal IPs or ranges.

    Example pattern:

    ip ∉ 1.2.3.4, 5.6.7.8 (doesn’t contain these IPs)

    This means that when the toggle is on, PostHog will show events whose IP does not match your office IPs (i.e. real users).

  2. At tracking time (for ingestion control):
    If you want to avoid sending events at all from office IPs, implement logic in your backend or frontend to skip tracking when the request comes from a known internal IP.

The most stable approach is:

  • Use a person property like email and filter for “doesn’t contain @yourcompany.com” so you only see users who aren’t internal. PostHog’s own tutorial uses this pattern:

    email ∉ @posthog.com (“doesn’t contain”).

  • Alternatively, add a dedicated boolean property like is_employee or is_test_user to your events or people and filter on that property.

Then add that filter in Project settings → Filter out internal and test users and toggle the feature on inside your insights.

Very common pattern:

  • Host-based filters:
    Add a filter on the Host property and exclude your dev environments, e.g.:

    Host ≠ localhost:8000, localhost:3000, staging.yourapp.com

  • URL or query param filters:
    If QA uses special URLs like ?test_session=true, filter out events where Current URL contains test_session=true or where a custom property is_test_session is true.

You can combine these with email/IP filters so that both staging traffic and internal people on production are excluded when the toggle is on.

Yes, and PostHog explicitly recommends it now for person-property–based internal filtering:

  • Create a cohort that defines internal users (e.g. email domain, role property, or custom flags).

  • In Project settings → Filter out internal and test users, add a filter like “Person is not in cohort Internal users”.

This gives you a single place to update who counts as internal (the cohort), which is cleaner when people join/leave the company or when you change criteria.

Live/Activity views often show all events as they arrive, while product analytics insights may apply:

  • Your “Filter out internal and test users” toggle

  • Any other filters on the insight or dashboard

If you’re missing events in charts but can see them in real-time views, the first thing to check is whether internal/test filtering is turned on and whether your filters are accidentally excluding too much traffic.

IP-based filtering alone breaks down when:

  • People use dynamic home IPs

  • Everyone connects through a VPN or multiple exit nodes

In those cases, use identity-based filters instead of just network-based ones:

  • Email domain: email doesn’t contain @yourcompany.com

  • A boolean flag: is_employee = true

  • Cohorts built from HR / directory data

Then apply those cohorts or person properties in “Filter out internal and test users” so internal people are excluded regardless of where they’re connecting from. (+)

Yes. The internal and test user filter is a product feature that works in both PostHog Cloud and self-hosted instances. The GitHub issue discussing confusion around the filter specifically references both environments.

The UI and behavior are essentially the same: you configure filters in project settings and toggle them per-insight.

Some recurring problems PostHog has seen:

  • Using the wrong operator direction – e.g.

    • email contains @yourcompany.com instead of email doesn’t contain @yourcompany.com, which can result in no data when the toggle is on. This has been common enough to be logged as a UX issue.

  • Filtering on properties that aren’t set everywhere, which can unintentionally drop events that don’t have that property.

  • Expecting filters to be retroactive on person changes – PostHog stores a snapshot of person properties at event time; removing or changing a property later doesn’t change historical events.

Double-check filter logic (“doesn’t contain” vs “contains”) and confirm which events actually have the properties you’re filtering on.

A simple validation workflow:

  1. Use a known internal session:
    Visit your app as an internal user (office IP, internal email, etc.) and trigger a few events.

  2. Check Live / Activity:
    Confirm those events appear there.

  3. Open a test insight:

    • With the internal filter off, you should see those internal events.

    • With the filter on, those internal events should disappear from the graph or table.

If they’re still showing when the toggle is on, your filter conditions are likely too broad, pointed at the wrong property, or inverted (using “contains” instead of “doesn’t contain”).

Use both, for different reasons:

  • PostHog internal user filtering (this article):
    Great for analysis – you keep all raw data but exclude internal users from reports, funnels, and dashboards.

  • Instrumentation-level exclusion:
    Useful when you want to avoid sending events at all from certain environments or users:

    • Disable tracking on localhost and staging hosts

    • Add config flags that skip tracking for employees

    • Use backend checks to avoid logging internal system actions

For most teams, the practical setup is: disable obvious dev/staging noise in code, then use PostHog’s “Filter out internal and test users” to clean up anything that still makes it through.

Related blog posts

Leave a Reply

Your email address will not be published. Required fields are marked *