PostHog Integration
PostHog is Opsis's session replay source. You connect it with one click via OAuth — there are no API keys, project IDs, or host URLs to copy.
Connect with OAuth
- On the onboarding screen, choose PostHog and click Connect your project. (On an existing project, the PostHog card lives on the Integrations tab.)
- You're sent to PostHog to authorize Opsis. Opsis requests the minimum read-only scopes it needs:
organization:read,project:read,session_recording:read, andquery:read, plus basic OIDC identity (openid,profile,email). - PostHog sends you back to Opsis. If your account has more than one project, pick the project to analyze.
- Opsis imports your recent session replays and starts catching the bugs you'd never test for. You can pull in newer replays anytime with Scan now. Nothing else to configure.
Make sure session replay is enabled on the project you connect (PostHog → Settings → Session replay → Record user sessions), otherwise there are no recordings to analyze.
Security
- Opsis never sees your PostHog password and never asks for an API key.
- OAuth access & refresh tokens are encrypted at rest (AES-256-GCM) and never sent to your browser.
- Opsis requests read-only scopes and never writes back to PostHog.
- You can revoke access anytime — from your Opsis project's Integrations tab (Disconnect) or from PostHog's app settings. Disconnecting revokes Opsis's tokens with PostHog and deletes them from Opsis.
Reconnect and Disconnect live on your project's Integrations tab, in the PostHog card. Reconnecting (or connecting the same PostHog project again) re-attaches to your existing Opsis project — it never creates a duplicate.
What Opsis imports
- Recording metadata: duration, browser/device/OS, start URL, replay link.
- Events per session (HogQL query via
query:read):$pageview,$autocapture,$rageclick,$dead_click, and$exception. - All text passes through redaction before being stored or analyzed.
The connector uses adapters + graceful fallbacks: endpoints unavailable in your PostHog deployment do not break the import — missing data is simply left empty.
Don't use PostHog yet?
Add PostHog session replay to your app first, let it record some real traffic, then come back and connect with OAuth:
- Install
posthog-jsand initialize it with session recording, console capture, and error capture enabled — the last two give Opsis hard evidence (console errors, exceptions) instead of behavioral guesses:npm install posthog-jsPrefer not to touch your bundle? PostHog's HTML snippet (PostHog → Settings → Web snippet) works just as well.import posthog from "posthog-js"; posthog.init("phc_xxxxx", { // your PostHog project API key api_host: "https://us.i.posthog.com", // or your PostHog region/host session_recording: { maskAllInputs: true, // recommended: mask user input }, enable_recording_console_log: true, // console errors as bug evidence capture_exceptions: true, // uncaught errors as bug evidence }); - Enable Session Replay in PostHog (Settings → Session replay → Record user sessions).
- Back in Opsis, choose PostHog and click Connect your project.
Note: phc_… is PostHog's public, browser-safe ingestion key for recording sessions — it is not an Opsis credential and is never used to connect Opsis to PostHog. Connecting Opsis is always done through OAuth.
Troubleshooting: connected, but zero recordings
Your PostHog project is connected but a scan imports 0 sessions? The usual causes, in order of likelihood:
- The snippet is live but recording is off. posthog-js sends events, but replays only exist when Record user sessions is enabled (PostHog → Settings → Session replay). Flip it on, generate a visit, and scan again.
- No real visits yet. A just-deployed app has nothing to record — a couple of your own page views are enough, and recordings can take a few minutes to appear in PostHog after the visit.
- Ad blockers. Browser ad/tracking blockers commonly block posthog-js, so your own test visits may never reach PostHog. Try a browser profile with blockers disabled when generating test traffic.
- Masked inputs are not missing data. With
maskAllInputs: true(recommended), typed input appears masked in replays by design — Opsis still gets the events and error signals it needs. Don't turn masking off to “fix” recordings.