PLG Engineering

PostHog for PLG: The Technical Infrastructure Guide

Most PLG failures are not strategy failures. They are instrumentation failures — teams that cannot see which users activated, which accounts are expanding, or which acquisition channels are producing trial users who actually convert. This guide covers the three technical layers that fix that.

Jake McMahon 12 min read Jake McMahon Published March 28, 2026
PostHog PLG infrastructure: attribution persistency, PQL scoring engine, and reverse ETL bridge

TL;DR

  • Attribution Persistency: Configure $initial_utm_source persistence so the marketing origin of every user is locked to their profile on signup — not overwritten by direct traffic on return visits.
  • The Aha Moment Pipeline: Move beyond login tracking. Instrument technical milestones like first_api_call_completed or integration_connected to calculate real Time-to-Value.
  • PQL Scoring Engine: Use HogQL to score organizations on velocity, breadth, and integration depth. Automate the alert when an account crosses the threshold.
  • The Reverse ETL Bridge: Use PostHog Data Pipelines (or Census / Hightouch on top of a warehouse export) to push behavioral account signals into HubSpot, Salesforce, or Intercom in real time.
  • Group Analytics: Call posthog.group() on every event to aggregate individual behavior at the account level — this is what makes B2B PLG metrics meaningful.

PLG is an infrastructure problem

Product-Led Growth gets framed as a go-to-market decision. A choice between sales-led and self-serve. A positioning call. That framing is wrong — or at least incomplete.

PLG is an instrumentation decision. The question is not "should we let users try before they buy?" Most SaaS products already do. The question is whether your analytics stack can answer the questions that PLG depends on:

  • Which acquisition channel produces users who activate fastest?
  • Which organizations are expanding their internal usage right now — before sales knows about it?
  • Which accounts hit the Aha Moment but never upgraded? Why?
  • What is the Time-to-Value for users who came through paid versus organic?

If your analytics cannot answer those questions at the account level, you do not have a PLG motion. You have a self-serve trial with no feedback loop.

PostHog is one of the few analytics platforms built to answer all of them from a single SDK. It combines product analytics, feature flags, session replay, A/B testing, and a SQL query engine (HogQL) into one stack — which removes the integration latency that plagues fragmented tool sets.

This guide covers the three technical layers in order of implementation priority. If you want them implemented correctly from the start rather than patched after the fact, our PostHog consulting work is scoped specifically around PLG instrumentation.

1. Solving Attribution Persistency

The single most common failure in PLG analytics is losing the marketing origin of a user between their first visit and their paid conversion.

Here is the typical failure mode: a user clicks a paid LinkedIn ad, visits your pricing page, leaves without signing up. Three days later they return directly. They sign up. Your analytics records them as "Direct" traffic. Your CAC model now undercounts LinkedIn's contribution to that conversion by 100%.

PostHog solves this through Person Profiles and the $initial_utm_source property. When the PostHog JS SDK initializes, it captures UTM parameters from the URL and writes them as initial properties on the person profile — properties that are written once and never overwritten, regardless of how many future sessions the user has.

How the identity merge works

The mechanism that makes this work across devices and sessions is posthog.identify(). When a user signs up and your application calls posthog.identify('user_id_123'), PostHog merges the anonymous pre-signup person profile (which holds the initial UTM data) into the identified profile. From that point on, every event fired by that user — including future subscription events — carries the original attribution.

One critical configuration: set person_profiles to 'identified_only' if you want to avoid creating person records for anonymous visitors who never sign up. This keeps your billing clean and your data focused on users who matter for PLG analysis.

-- HogQL: Revenue by original acquisition channel SELECT properties.$initial_utm_source AS source, properties.$initial_utm_campaign AS campaign, count(DISTINCT person_id) AS paid_conversions, sum(toFloat64OrZero(properties.contract_value)) AS total_revenue, round( sum(toFloat64OrZero(properties.contract_value)) / count(DISTINCT person_id), 0 ) AS avg_contract_value FROM events WHERE event = 'subscription_started' AND toDate(timestamp) >= today() - interval 90 day GROUP BY source, campaign ORDER BY total_revenue DESC

The reverse proxy requirement

Attribution persistency only works if PostHog actually receives the event in the first place. Ad blockers and privacy-focused browsers block the us.i.posthog.com endpoint by default. For PLG, where marketing channels are the core measurement surface, this is not a minor data quality issue — it is a structural blind spot.

The fix is a Reverse Proxy. Route PostHog SDK calls through your own domain (e.g., analytics.yourdomain.com) so the requests appear as first-party. PostHog's documentation covers the Cloudflare Worker and Nginx configurations. This is a one-time setup that typically takes an engineer two hours. It is worth doing before you run any attribution analysis.

~30%

Estimated share of analytics events blocked by ad blockers in B2B SaaS — concentrated in the developer and technical buyer segments most likely to self-serve. A reverse proxy closes this gap entirely.

2. Building the PQL Scoring Engine

Three PQL scoring signals: velocity over 50%, breadth of 3+ unique users, and integration connection event
The three signals that define a Viral Pocket: usage velocity, organizational breadth, and third-party integration depth.

A Product Qualified Lead (PQL) is not a "high-activity user." High activity in a free tier is noise. A PQL is an organization that has achieved enough value density — across enough users, with enough commitment — that an upgrade conversation is both timely and welcome.

The distinction matters because the actions are different. A high-activity single user gets an in-app nudge. A PQL account gets a human outreach from an account executive who already knows which features they have explored.

The Viral Pocket Formula

We look for three technical signals at the organization level, not the user level. PostHog's Group Analytics feature makes this possible by aggregating individual events up to a defined group type — in B2B, this is almost always organization or account.

Set up the group on every event by calling:

posthog.group('organization', organizationId, { name: organizationName, plan: currentPlan, created_at: accountCreatedAt, seat_count: activeSeats })

Once group data is flowing, the three PQL signals are:

  • Velocity: Core feature usage increased more than 50% week-over-week. A team that accelerates like this has found a repeatable workflow — they are no longer experimenting.
  • Breadth: More than 3 unique users within one domain have performed creation-type events in the last 14 days. One power user is a fan. Three creation-type users is an organizational buying signal.
  • Integration: The organization has fired an integration_connected event with a third-party provider (Stripe, Salesforce, Zapier). Integration events are the strongest commitment signal in self-serve B2B — teams do not wire their production data into tools they are not serious about.

"The most valuable signal in B2B PLG is not how often one person logs in — it is how fast the organizational surface area of your product is expanding. If usage jumps from 1 user to 5 in 48 hours, that is a PQL red alert."

— Jake McMahon, ProductQuant

Scoring with HogQL

PostHog's HogQL (a ClickHouse-compatible SQL dialect) lets you query the full event history and compute scores directly in PostHog — without exporting to a warehouse first. This is the query pattern for a weighted PQL score at the group level:

-- HogQL: PQL score per organization (last 14 days) SELECT properties.$group_0 AS org_id, groupProperties.$group_0['name'] AS org_name, -- Velocity signal: WoW growth on core feature events countIf( event = 'core_feature_used' AND toDate(timestamp) >= today() - interval 7 day ) AS events_this_week, countIf( event = 'core_feature_used' AND toDate(timestamp) BETWEEN today() - interval 14 day AND today() - interval 7 day ) AS events_last_week, -- Breadth signal: unique active users uniqIf( distinct_id, event = 'creation_event' AND toDate(timestamp) >= today() - interval 14 day ) AS active_creators, -- Integration signal countIf(event = 'integration_connected') AS integrations_connected, -- Composite score ( if(events_this_week > events_last_week * 1.5, 40, 0) + if(active_creators >= 3, 35, active_creators * 10) + if(integrations_connected >= 1, 25, 0) ) AS pql_score FROM events WHERE toDate(timestamp) >= today() - interval 14 day AND properties.$group_0 IS NOT NULL GROUP BY org_id, org_name HAVING pql_score >= 75 ORDER BY pql_score DESC

Accounts that score 75 or above are flagged as PQLs. The threshold is a starting point — calibrate it against your actual conversion data after the first 30 days of running the query.

Implementation note: Save this HogQL query as a PostHog Insight and pin it to a dashboard. Then use a PostHog Webhook destination (under Data Pipelines) to fire a Slack or HubSpot notification whenever the query returns new rows. This creates a near-real-time PQL alert without a separate data pipeline.

PLG Audit

Is your PQL scoring engine actually running?

Most teams have the events. They do not have the scoring logic. We audit your PostHog setup and ship your first working PQL alert in two weeks.

3. The Reverse ETL Bridge: Analytics to Action

Before and after comparison of PostHog reverse ETL: without it, sales works from lagging manual signals; with it, teams act on real-time product intent
Reverse ETL closes the gap between product behavior and sales action — replacing manual report pulls with real-time intent signals in the CRM.

Data that sits in a PostHog dashboard is analytically interesting and commercially useless. For PLG to work, product signals need to live where sales and success teams live: inside HubSpot, Salesforce, or Intercom.

This is what Reverse ETL means: moving enriched, aggregated data back from your analytics layer into operational tools. The direction is the reverse of a standard integration. Instead of CRM data flowing into your product, product behavior flows into the CRM.

PostHog Data Pipelines

PostHog has a native Data Pipelines feature (formerly called "Destinations") that lets you stream events and person property updates to external tools without a warehouse in the middle. For smaller event volumes, this is the fastest path to Reverse ETL.

For higher volumes, or when you want transformation logic before the data hits your CRM, the standard architecture is: PostHog exports to a warehouse (S3, BigQuery, Snowflake) via Batch Exports, and then Census or Hightouch syncs the transformed data into your operational tools on a schedule.

Signal PostHog event / property Sales or CS action
Aha Moment reached first_successful_deployment Automated "congrats" sequence + best practices guide via Intercom
Usage ceiling approaching hits_80_percent_of_tier_limit Account Executive task created in HubSpot for expansion conversation
Enterprise feature clicked enterprise_feature_clicked with feature_name property In-app upgrade nudge + AE notification if account is PQL
PQL threshold crossed Computed property: pql_score >= 75 Salesforce lead status updated to "PQL" — triggers AE outreach sequence
Key integration connected integration_connected with provider CS tagged for check-in — integration events predict 30-day retention

The Integration Tax

Teams that run PostHog alongside Amplitude for analytics, LaunchDarkly for feature flags, and a separate A/B testing tool pay what we call the Integration Tax: the 2–4 week engineering cost each time you need to connect a behavioral signal from one tool to an action in another.

Want to show a targeted in-app message to users who are in a specific feature flag cohort and have not yet triggered the activation event? In a fragmented stack, that requires an export, a join, a re-import, and a wait. In PostHog, it is a single audience filter using Feature Flags and Cohort conditions on the same event stream.

The consolidation argument for PostHog in a PLG context is not about cost. It is about cycle time. The faster you can run an activation experiment, the more experiments you run, the faster you find what actually moves Time-to-Value.

4. Instrumenting the Aha Moment

Time-to-Value (TTV) is the PLG metric that matters most in the first 14 days of a trial. But most teams measure TTV from signup to first login — which tells you nothing about whether the user got any value.

The Aha Moment is the specific product event that correlates with long-term retention. It is not a milestone you choose by intuition. You find it by comparing the event history of users who converted against users who churned after a trial and looking for the event that is most predictive.

PostHog Funnel Analysis and Correlation Analysis (under the Insights section) are the two tools for this. Build a funnel from signup to paid conversion and then run a correlation analysis on events in the middle. PostHog will surface which events are statistically associated with conversion — ranked by relative risk ratio.

What to instrument, exactly

Generic events like page_viewed or feature_tab_clicked will not help. The events that predict Aha Moments are outcome events — actions that represent delivered value, not interface interaction:

  • first_api_call_completed — the user's code is actually running against your API
  • first_report_generated — the user has produced an output they can share
  • first_team_member_invited — the user has made the product social within their organization
  • first_automated_workflow_triggered — the product is now working without manual input
  • integration_connected — the user has committed production data to the platform

Instrument these as distinct named events with relevant properties. Then measure the median time from signup to each event across converted versus churned cohorts. The event where the gap is largest is your Aha Moment candidate.

The Aha Moment is not where users say "I like this." It is where the product becomes genuinely difficult to remove from their workflow.

Once you have identified the Aha Moment event, track Time-to-Value as a PostHog Session Recording filter anchor. Watch recordings of users who took more than 48 hours to reach the event. The friction points will be obvious — and they will be specific enough to fix.

5. HIPAA, Multi-Tenancy, and Compliance Architecture

PLG works in regulated markets. The mechanics are the same — the infrastructure choices are different.

HIPAA-compliant PostHog deployments

PostHog's Private Cloud option (a dedicated EU or US instance running in a VPC you control) is the path to HIPAA compliance. Under this configuration, behavioral data never passes through PostHog's shared infrastructure. PostHog will sign a BAA for Private Cloud deployments.

The alternative — self-hosting PostHog on your own Kubernetes cluster — gives you full control over data residency but requires your engineering team to manage upgrades, backups, and scaling. For most Series A/B companies, the Private Cloud option is the better trade.

Feature flags and session replay can both be scoped or disabled per-user to avoid capturing PHI. Use the posthog.opt_out_capturing() call on user profiles that have opted out of analytics tracking.

Multi-tenant B2B tracking

The key implementation detail for multi-tenant SaaS is ensuring that every event carries both the distinct_id (the individual user) and the group identifier (the organization or workspace). Without the group call, PostHog can answer user-level questions but not account-level ones — and in B2B, account-level is almost always what matters.

Call posthog.group('organization', orgId) on every page load after authentication, not just on the events you think are "important." Group association needs to be consistent across the event stream to make Group Analytics work correctly.

// Initialize with group on every authenticated page load posthog.identify(userId, { email: user.email, name: user.name, plan: user.plan, created_at: user.createdAt }) posthog.group('organization', user.orgId, { name: user.orgName, plan: user.orgPlan, seat_count: user.orgSeats, mrr: user.orgMrr // if you have this — useful for expansion scoring })

Common Implementation Questions

Should we use PostHog Cloud or self-host?

For most B2B SaaS teams at Series A or B, PostHog Cloud (the managed US or EU instance) is the right default. You get automatic upgrades, managed infrastructure, and the full feature set without a dedicated ops burden. The free tier covers 1 million events per month — enough for most early-stage PLG instrumentation.

Self-hosting makes sense when your compliance requirements mandate on-premises data residency, or when your event volume is large enough that Cloud billing becomes material. PostHog is open source under the MIT license for the core features, so the self-hosted path is technically viable — it just requires engineering investment.

How do we avoid polluting the event stream with test data?

Use separate PostHog projects for staging and production — not environment flags within a single project. This is the cleanest separation and avoids the risk of test events contaminating your activation and PQL analysis. PostHog projects are free to create and have independent API keys.

Within production, filter out internal users using a PostHog Person Property filter on your dashboards and insights: exclude events where email contains your company domain. Add this filter as a global filter on your PLG dashboard so it applies everywhere.

What is the right event taxonomy for PLG?

Keep it flat and outcome-focused. The temptation in early instrumentation is to track everything — every click, every hover, every tab switch. This creates noise that makes analysis slower without improving signal quality.

Start with three event categories: activation milestones (the 5–8 events on the path to the Aha Moment), retention actions (the events that correlate with weekly active use), and expansion signals (events that indicate a team is ready to upgrade). Name them with object_action syntax: report_created, integration_connected, seat_invited. Add a single plan property to every event so you can filter by tier in any query.

How long does a full PLG instrumentation take to implement?

The core SDK setup — identity, group calls, and the first 10 activation events — takes one focused engineering sprint (1–2 weeks). The reverse proxy configuration is a half-day task. The PQL scoring query and webhook alert can be set up in PostHog in a few hours once the event data is flowing.

The longer work is calibration: figuring out which events actually predict conversion, setting the right PQL threshold, and tuning the reverse ETL sync frequency. Budget 30–60 days of iteration after the initial setup before the signals are reliable enough to drive sales actions.

Sources

Free tools: Score your PLG readiness in 2 minutes → PLG Readiness Score · Get the optimal trial length for your product → Free Trial Length Calculator

Jake McMahon

About the Author

Jake McMahon is a PLG and GTM growth consultant who has architected product analytics stacks for Series A–C B2B SaaS companies. He specializes in the technical instrumentation of activation and expansion loops, and has led migrations of 100M+ events from legacy stacks into PostHog. If your PLG funnel has gaps, get in touch.