Geek Logbook

Tech sea log book

Tracking Subdomains in PostHog Without Breaking User Journeys

When a website grows, it often stops being just one site. A main domain may coexist with multiple subdomains, such as a marketing site, an events portal, a documentation site, or a learning platform.

At that point, a common analytics question appears:

Do I need to install PostHog separately on each subdomain, and how do I track users across all of them?

The answer is straightforward: yes, each frontend that should send analytics data must load PostHog, and the setup should be designed so that the same user can be recognized across subdomains.

The core rule

PostHog only captures events from pages where its JavaScript snippet or SDK is actually running.

That means:

  • if the main domain loads PostHog, it can capture activity there
  • if a subdomain does not load PostHog, that subdomain will not send pageviews, autocapture events, or custom events
  • if multiple subdomains should be analyzed, each relevant frontend must initialize PostHog

This is not a limitation of PostHog in particular. It is how client-side analytics works in general.

One project, multiple subdomains

In most cases, the best approach is to use a single PostHog project for the entire family of related sites.

For example, if a company has:

  • main website
  • help center
  • events platform
  • member portal

and all of them are part of the same user journey, placing them in one PostHog project usually makes analysis much easier.

This allows teams to answer questions such as:

  • how many users move from the marketing site to the product area
  • which acquisition source leads to engagement in other subdomains
  • where users drop off across the broader web experience

Splitting each subdomain into a different PostHog project usually makes this harder, unless there is a strong governance or data isolation reason.

Do you need to install the code on both sites?

Yes, if both are separate frontends.

If the main domain and the subdomain are deployed independently, then both need PostHog initialization.

If they share a common base template, shell, or frontend layout, then it may be enough to initialize PostHog once in that shared layer. But that is an architectural shortcut, not an analytics feature.

The operational rule remains the same: every page that should be tracked must load the PostHog client.

Recognizing the same user across subdomains

The next problem is identity continuity.

A user may start on one subdomain and then navigate to another. If cookies are not handled correctly, analytics may treat that same person as two different users.

In posthog-js, the relevant setting is cross_subdomain_cookie.

A typical initialization looks like this:

<script>
  posthog.init('YOUR_PROJECT_API_KEY', {
    api_host: 'https://us.i.posthog.com',
    cross_subdomain_cookie: true,
    persistence: 'localStorage+cookie'
  })
</script>

With this configuration, PostHog can store identification data at the parent domain level, which helps preserve continuity between subdomains.

In many setups, this is enough to maintain a shared identity across related subdomains.

Common mistake

A frequent mistake is assuming that if the main domain is instrumented, then subdomains are automatically included.

They are not.

If a subdomain has its own pages, templates, or frontend runtime, it must also load PostHog. Otherwise:

  • no pageviews will be captured there
  • no autocapture will happen there
  • no custom frontend events will be emitted from that subdomain

How to distinguish traffic by subdomain

Even when all subdomains live in the same PostHog project, teams still need a way to segment data by site section.

The simplest way is to register the hostname as a property.

Example:

posthog.register({
  hostname: window.location.hostname
})

That makes it easy to filter dashboards, funnels, and event streams by values such as:

  • www.example.com
  • events.example.com
  • docs.example.com

This is often enough for most reporting needs.

A more explicit option is to register a business-level property such as:

posthog.register({
site_section: 'events'
})

This is useful when hostnames are too technical or when several domains should map to a single business category.

When sessions still break

Even with shared cookies, there are cases where journeys across sites do not look clean:

  • self-referrals appear
  • a user seems to restart a session when moving between subdomains
  • the same person gets multiple identities

This usually happens because of cookie policies, browser behavior, inconsistent initialization, or a more complex navigation pattern between sites.

When that occurs, review:

  • whether the same PostHog project key is used everywhere
  • whether cross_subdomain_cookie is enabled
  • whether the analytics code loads consistently on all relevant sites
  • whether identity calls such as identify() are implemented the same way across applications

A practical recommendation

For most organizations, the right setup is:

  • use one PostHog project for all related subdomains
  • initialize PostHog on every frontend that should be tracked
  • keep cross-subdomain identity enabled
  • register hostname or site section as a property for filtering
  • validate the flow by navigating from one subdomain to another and checking live events

This creates a cleaner model for user journeys while still preserving the ability to analyze each subdomain independently.

Final thought

Subdomains often look like a technical infrastructure detail, but from an analytics perspective they are a boundary. If you do not instrument them deliberately, your data becomes fragmented exactly where user journeys become most interesting.

A good PostHog setup should reflect the actual product surface users experience, not just the main domain.