From be6d2489bee9095f5ea5233d26759475e8ba4f39 Mon Sep 17 00:00:00 2001 From: Marco Gancitano Date: Wed, 5 Aug 2026 09:46:46 -0400 Subject: [PATCH 1/3] Add AI observability wizard command to start here and installation docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wizard now ships a dedicated `ai-observability` command, so surface it in the AI Observability docs the same way other products do: - Installation index: add the standard "AI wizard" section with , mirroring error tracking, experiments, and surveys - Start here: offer the wizard as the fastest path in the first quest step, keeping the platform grid as the manual option - AI wizard page: add the `wizard ai-observability` row to the commands table - Flip wizardSupport from 'Coming soon' to true now that the CLI supports it - Fix doubled ↗ on the AI Observability nav link by dropping the literal arrow from the label and using a relative URL Co-Authored-By: Claude Fable 5 --- contents/docs/ai-engineering/ai-wizard.mdx | 1 + .../docs/ai-observability/installation/index.mdx | 12 +++++++++++- contents/docs/ai-observability/start-here.mdx | 7 ++++++- src/hooks/productData/ai_observability.tsx | 2 +- src/navs/index.js | 4 ++-- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/contents/docs/ai-engineering/ai-wizard.mdx b/contents/docs/ai-engineering/ai-wizard.mdx index 92e5284aade0..c011e7dc7b76 100644 --- a/contents/docs/ai-engineering/ai-wizard.mdx +++ b/contents/docs/ai-engineering/ai-wizard.mdx @@ -77,6 +77,7 @@ Running `npx @posthog/wizard` starts the default integration flow. The wizard al | `wizard audit ` | Audit an existing integration – see [Audit subcommands](#audit-subcommands) | | `wizard revenue-analytics` | Wire up Stripe + PostHog revenue analytics | | `wizard mcp-analytics` | Instrument your own MCP server with [MCP Analytics](/docs/mcp-analytics) | +| `wizard ai-observability` | Instrument your LLM calls with [AI Observability](/docs/ai-observability) | | `wizard migrate` | Migrate from another analytics or feature-flag vendor | | `wizard upload-source-maps` | Upload source maps to PostHog Error Tracking | | `wizard mcp add` / `wizard mcp remove` / `wizard mcp tutorial` | Manage the PostHog MCP server for your AI agent, or explore the MCP tutorial | diff --git a/contents/docs/ai-observability/installation/index.mdx b/contents/docs/ai-observability/installation/index.mdx index dd84509945a4..0b6cf6049d3f 100644 --- a/contents/docs/ai-observability/installation/index.mdx +++ b/contents/docs/ai-observability/installation/index.mdx @@ -3,8 +3,18 @@ title: Install AI Observability with PostHog --- import LLMAnalyticsInstallationPlatforms from '../_snippets/llms-installation-platforms' +import WizardCommand from 'components/WizardCommand' + +## AI wizard + +Install PostHog in seconds with our wizard by running this command in your project directory with your terminal (it also works for [LLM coding agents](/blog/envoy-wizard-llm-agent) like Cursor and Bolt): + + + +Wait for it to finish and test the setup once the wizard is complete. + +## Platforms Choose your platform below to get started with AI Observability installation. - diff --git a/contents/docs/ai-observability/start-here.mdx b/contents/docs/ai-observability/start-here.mdx index 4332aa1f08d7..859f9cb2d978 100644 --- a/contents/docs/ai-observability/start-here.mdx +++ b/contents/docs/ai-observability/start-here.mdx @@ -8,6 +8,7 @@ import { QuestLog, QuestLogItem } from 'components/Docs/QuestLog' import { IconGraph, IconWarning, IconRewindPlay } from '@posthog/icons' import LLMsInstallationPlatforms from './_snippets/llms-installation-platforms.tsx' import OSButton from 'components/OSButton' +import WizardCommand from 'components/WizardCommand' @@ -28,7 +29,11 @@ AI Observability gives you x-ray vision into your LLM applications. You can trac > **New to LLM observability?** See [core concepts](/docs/ai-observability/basics) for a primer on events, tokens, and traces. -The first step is to install a PostHog SDK to capture conversations, requests, and responses from an LLM provider. +The first step is to install a PostHog SDK to capture conversations, requests, and responses from an LLM provider. The fastest way is our wizard, which installs the SDK and instruments your LLM calls for you (it also works for [LLM coding agents](/blog/envoy-wizard-llm-agent) like Cursor and Bolt): + + + +Prefer to do it by hand? Choose your platform below: ### Platforms diff --git a/src/hooks/productData/ai_observability.tsx b/src/hooks/productData/ai_observability.tsx index d5c63c2c6b30..4c1348d16410 100644 --- a/src/hooks/productData/ai_observability.tsx +++ b/src/hooks/productData/ai_observability.tsx @@ -31,7 +31,7 @@ export const aiObservability = { forumTopicId: 390, color: 'purple', colorSecondary: 'green-2', - wizardSupport: 'Coming soon', + wizardSupport: true, pricingDescription: 'Generations, spans, and traces are captured as regular PostHog events and billed like them – no per-seat pricing, and no markup on the tokens you already pay your model provider for.', seo: { diff --git a/src/navs/index.js b/src/navs/index.js index 1a64cf778c0a..94ace3c45346 100644 --- a/src/navs/index.js +++ b/src/navs/index.js @@ -3705,8 +3705,8 @@ export const docsMenu = { url: '/docs/ai-engineering/skills-store', }, { - name: 'AI Observability ↗', - url: 'https://posthog.com/docs/ai-observability', + name: 'AI Observability', + url: '/docs/ai-observability', }, { name: 'Markdown and llms.txt', From 4cd7f73b6e6ad2c61d3c16bd4619e641d9d4d64c Mon Sep 17 00:00:00 2001 From: Marco Gancitano Date: Wed, 5 Aug 2026 10:34:51 -0400 Subject: [PATCH 2/3] Show AI observability wizard hint on platform installation pages Mirror the data warehouse pattern: the Handbook template now renders a dismissible wizard banner below the title of every AI observability platform installation page, pushing `npx @posthog/wizard ai-observability` as the automated alternative to manual SDK setup. - Extract the banner from WarehouseWizardHint into a generic WizardHint component (command, copy, and dismissal key as props); WarehouseWizardHint becomes a thin preconfigured wrapper so its call sites are unchanged - Add AIObservabilityWizardHint and render it from Handbook.tsx on /docs/ai-observability/installation/* paths, excluding the coding-agent integrations (Claude Code, OpenClaw, Pi) where the wizard doesn't apply - Wire pre-paint dismissal for the new key in theme-init.js and global.css Co-Authored-By: Claude Fable 5 --- .../AIObservabilityWizardHint/index.tsx | 18 +++++ src/components/WarehouseWizardHint/index.tsx | 69 +++--------------- src/components/WizardHint/README.md | 40 ++++++++++ src/components/WizardHint/index.tsx | 73 +++++++++++++++++++ src/styles/global.css | 4 + src/templates/Handbook.tsx | 14 +++- static/scripts/theme-init.js | 10 ++- 7 files changed, 166 insertions(+), 62 deletions(-) create mode 100644 src/components/AIObservabilityWizardHint/index.tsx create mode 100644 src/components/WizardHint/README.md create mode 100644 src/components/WizardHint/index.tsx diff --git a/src/components/AIObservabilityWizardHint/index.tsx b/src/components/AIObservabilityWizardHint/index.tsx new file mode 100644 index 000000000000..210597bec8e8 --- /dev/null +++ b/src/components/AIObservabilityWizardHint/index.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import WizardHint from 'components/WizardHint' + +/** + * WizardHint preconfigured for AI observability: pushes `npx @posthog/wizard ai-observability`, + * which installs the SDK and instruments a project's LLM calls instead of setting them up by hand. + */ +export default function AIObservabilityWizardHint({ className = '' }: { className?: string }): JSX.Element { + return ( + + ) +} diff --git a/src/components/WarehouseWizardHint/index.tsx b/src/components/WarehouseWizardHint/index.tsx index 34e8c181620d..a7f3400601c2 100644 --- a/src/components/WarehouseWizardHint/index.tsx +++ b/src/components/WarehouseWizardHint/index.tsx @@ -1,65 +1,20 @@ import React from 'react' -import { IconX } from '@posthog/icons' -import CloudinaryImage from 'components/CloudinaryImage' -import WizardCommand from 'components/WizardCommand' - -// Persist dismissal so the hint doesn't nag a user who has already seen it. Mirrors the -// product app's WarehouseWizardHint, which uses the same localStorage key. -// theme-init.js sets `warehouse-wizard-hint-dismissed` on before paint when this -// key is set; global.css hides `.warehouse-wizard-hint` when that class is present. -const DISMISSED_KEY = 'warehouse-wizard-hint-dismissed' -const DISMISSED_CLASS = 'warehouse-wizard-hint-dismissed' +import WizardHint from 'components/WizardHint' /** - * Agent-flavored nudge that pushes the `npx @posthog/wizard warehouse` CLI, which auto-detects - * and connects a user's databases/APIs straight from their codebase instead of setting up a - * source by hand. Visual design matches [`WizardCTA`](../WizardCTA). + * WizardHint preconfigured for the data warehouse: pushes `npx @posthog/wizard warehouse`, which + * auto-detects and connects a user's databases/APIs straight from their codebase instead of + * setting up a source by hand. The dismissal key mirrors the product app's WarehouseWizardHint, + * which uses the same localStorage key. */ export default function WarehouseWizardHint({ className = '' }: { className?: string }): JSX.Element { - const handleDismiss = () => { - localStorage.setItem(DISMISSED_KEY, '1') - document.documentElement.classList.add(DISMISSED_CLASS) - } - return ( -
- -
- - -
-
-

Let AI connect your sources for you

-

- Skip the manual setup — run this in your project and the wizard auto-detects your databases - and APIs and connects them to PostHog. -

- -
-
- PostHog Wizard hedgehog -
-
-
-
+ ) } diff --git a/src/components/WizardHint/README.md b/src/components/WizardHint/README.md new file mode 100644 index 000000000000..2f2d212dfd5a --- /dev/null +++ b/src/components/WizardHint/README.md @@ -0,0 +1,40 @@ +# WizardHint + +Dismissible banner that nudges readers toward a `npx @posthog/wizard ` CLI flow as the automated alternative to manual setup. Visual design matches `WizardCTA` (wizard hedgehog, tan texture background, inline copyable command). + +## Usage + +```tsx +import WizardHint from 'components/WizardHint' + + +``` + +Prefer the preconfigured variants where one exists: + +- `components/WarehouseWizardHint` — data warehouse sources (`npx @posthog/wizard warehouse`). Rendered by `templates/DataWarehouseSource.tsx`, `templates/Handbook.tsx` (data warehouse source paths), and `pages/context-warehouse/sources.tsx`. +- `components/AIObservabilityWizardHint` — AI observability SDK installation (`npx @posthog/wizard ai-observability`). Rendered by `templates/Handbook.tsx` on `/docs/ai-observability/installation/*` pages. + +## Props + +| Prop | Type | Description | +| --- | --- | --- | +| `command` | `string` | Wizard subcommand appended to `npx @posthog/wizard` | +| `title` | `string` | Bold headline | +| `subtitle` | `string` | Supporting line under the headline | +| `dismissKey` | `string` | Base name for the dismissal wiring (see below) | +| `className` | `string?` | Extra classes on the outer wrapper | + +## Dismissal wiring + +Dismissing stores `${dismissKey}-dismissed = '1'` in localStorage and adds the same class to ``. To hide the hint before first paint on later visits, each variant needs two static registrations: + +1. `static/scripts/theme-init.js` — add the key to the dismissed-hint list so the `` class is set pre-paint. +2. `src/styles/global.css` — add a `html.-dismissed . { display: none; }` rule (the component puts `dismissKey` on its wrapper as a class). + +The `warehouse-wizard-hint` key mirrors the product app's hint, which shares the same localStorage key. diff --git a/src/components/WizardHint/index.tsx b/src/components/WizardHint/index.tsx new file mode 100644 index 000000000000..267f7d7cb70a --- /dev/null +++ b/src/components/WizardHint/index.tsx @@ -0,0 +1,73 @@ +import React from 'react' +import { IconX } from '@posthog/icons' +import CloudinaryImage from 'components/CloudinaryImage' +import WizardCommand from 'components/WizardCommand' + +/** + * Dismissible agent-flavored nudge that pushes a `npx @posthog/wizard ` CLI flow as the + * automated alternative to manual setup. Visual design matches [`WizardCTA`](../WizardCTA). + * + * Dismissal persists in localStorage under `${dismissKey}-dismissed`. theme-init.js reads that key + * before first paint and sets the same class on ; a per-variant rule in global.css hides the + * hint (matched by the `dismissKey` class on the wrapper). Adding a new variant means wiring the + * new key in both places — see the README. + */ +export default function WizardHint({ + command, + title, + subtitle, + dismissKey, + className = '', +}: { + /** Wizard subcommand, e.g. "warehouse" or "ai-observability" */ + command: string + title: string + subtitle: string + /** Base name for the dismissal localStorage key, class, and wrapper class */ + dismissKey: string + className?: string +}): JSX.Element { + const handleDismiss = () => { + localStorage.setItem(`${dismissKey}-dismissed`, '1') + document.documentElement.classList.add(`${dismissKey}-dismissed`) + } + + return ( +
+ +
+ + +
+
+

{title}

+

{subtitle}

+ +
+
+ PostHog Wizard hedgehog +
+
+
+
+ ) +} diff --git a/src/styles/global.css b/src/styles/global.css index 274e9ff573c0..150ab4321deb 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -3156,3 +3156,7 @@ div[data-radix-popper-content-wrapper] { html.warehouse-wizard-hint-dismissed .warehouse-wizard-hint { display: none; } + +html.ai-observability-wizard-hint-dismissed .ai-observability-wizard-hint { + display: none; +} diff --git a/src/templates/Handbook.tsx b/src/templates/Handbook.tsx index a6892f14474a..1b20f1cd10f6 100644 --- a/src/templates/Handbook.tsx +++ b/src/templates/Handbook.tsx @@ -30,6 +30,7 @@ import IsEU from 'components/IsEU' import IsUS from 'components/IsUS' import { CallToAction } from 'components/CallToAction' import WarehouseWizardHint from 'components/WarehouseWizardHint' +import AIObservabilityWizardHint from 'components/AIObservabilityWizardHint' import Tooltip from 'components/Tooltip' import NewsletterForm from 'components/NewsletterForm' import { MDXRenderer } from 'gatsby-plugin-mdx' @@ -364,6 +365,14 @@ export default function Handbook({ data: { post, postHogSource }, pageContext: { pathname === '/docs/data-warehouse/sources' || pathname.startsWith('/docs/data-warehouse/sources/') + // Same nudge for AI observability SDK installation pages. The coding-agent integrations + // (Claude Code, OpenClaw, Pi) are excluded: they instrument the agent itself, so running + // the wizard in a project doesn't set them up. The installation index has its own + // AI wizard section in the MDX. + const showAIObservabilityWizardHint = + pathname.startsWith('/docs/ai-observability/installation/') && + !['claude-code', 'openclaw', 'pi'].includes(pathname.split('/').filter(Boolean).pop() ?? '') + // Track product interest for cross-subdomain cookie useProductInterestFromPathname(slug) @@ -447,7 +456,10 @@ export default function Handbook({ data: { post, postHogSource }, pageContext: { : null), }} title={title} - belowTitle={showWarehouseWizardHint && } + belowTitle={ + (showWarehouseWizardHint && ) || + (showAIObservabilityWizardHint && ) + } tableOfContents={frontmatterTableOfContents || tableOfContents} mdxComponents={components} commits={commits} diff --git a/static/scripts/theme-init.js b/static/scripts/theme-init.js index bf4da35959b8..bc708fdf9e70 100644 --- a/static/scripts/theme-init.js +++ b/static/scripts/theme-init.js @@ -39,10 +39,12 @@ ) } catch (err) {} - // Hide dismissed WarehouseWizardHint before first paint + // Hide dismissed WizardHint variants before first paint try { - if (localStorage.getItem('warehouse-wizard-hint-dismissed') === '1') { - document.documentElement.classList.add('warehouse-wizard-hint-dismissed') - } + ;['warehouse-wizard-hint-dismissed', 'ai-observability-wizard-hint-dismissed'].forEach(function (key) { + if (localStorage.getItem(key) === '1') { + document.documentElement.classList.add(key) + } + }) } catch (err) {} })() \ No newline at end of file From a370e6a3d0becf8277628b191c28ee6dc9ec09df Mon Sep 17 00:00:00 2001 From: Marco Gancitano Date: Wed, 5 Aug 2026 10:49:10 -0400 Subject: [PATCH 3/3] Collapse the wizard hint instead of hiding it permanently Closing the WizardHint banner now collapses it to a slim bar (hedgehog, title, chevron) that expands back to the full banner on click, so the wizard command stays reachable after dismissal. Both states are always rendered and CSS keyed on the pre-paint class decides which shows, so the persisted state applies with no flash. Expanding clears the stored preference. Applies to both the warehouse and AI observability variants. Co-Authored-By: Claude Fable 5 --- src/components/WizardHint/README.md | 10 +-- src/components/WizardHint/index.tsx | 99 +++++++++++++++++------------ src/styles/global.css | 13 +++- 3 files changed, 75 insertions(+), 47 deletions(-) diff --git a/src/components/WizardHint/README.md b/src/components/WizardHint/README.md index 2f2d212dfd5a..6355435cdc3e 100644 --- a/src/components/WizardHint/README.md +++ b/src/components/WizardHint/README.md @@ -1,6 +1,6 @@ # WizardHint -Dismissible banner that nudges readers toward a `npx @posthog/wizard ` CLI flow as the automated alternative to manual setup. Visual design matches `WizardCTA` (wizard hedgehog, tan texture background, inline copyable command). +Collapsible banner that nudges readers toward a `npx @posthog/wizard ` CLI flow as the automated alternative to manual setup. Visual design matches `WizardCTA` (wizard hedgehog, tan texture background, inline copyable command). Closing it collapses to a slim bar (hedgehog + title + chevron) that expands back to the full banner on click, so the command stays reachable. ## Usage @@ -27,14 +27,14 @@ Prefer the preconfigured variants where one exists: | `command` | `string` | Wizard subcommand appended to `npx @posthog/wizard` | | `title` | `string` | Bold headline | | `subtitle` | `string` | Supporting line under the headline | -| `dismissKey` | `string` | Base name for the dismissal wiring (see below) | +| `dismissKey` | `string` | Base name for the collapse wiring (see below) | | `className` | `string?` | Extra classes on the outer wrapper | -## Dismissal wiring +## Collapse wiring -Dismissing stores `${dismissKey}-dismissed = '1'` in localStorage and adds the same class to ``. To hide the hint before first paint on later visits, each variant needs two static registrations: +Collapsing stores `${dismissKey}-dismissed = '1'` in localStorage and adds the same class to ``; expanding removes both. Both states are always rendered — CSS keyed on the `` class decides which one shows, so the collapsed state applies before first paint with no hydration flash. Each variant needs two static registrations: 1. `static/scripts/theme-init.js` — add the key to the dismissed-hint list so the `` class is set pre-paint. -2. `src/styles/global.css` — add a `html.-dismissed . { display: none; }` rule (the component puts `dismissKey` on its wrapper as a class). +2. `src/styles/global.css` — extend the two `.wizard-hint-full` / `.wizard-hint-collapsed` rule groups with the new variant's `html.-dismissed .` selectors. The `warehouse-wizard-hint` key mirrors the product app's hint, which shares the same localStorage key. diff --git a/src/components/WizardHint/index.tsx b/src/components/WizardHint/index.tsx index 267f7d7cb70a..d007d36fc5fb 100644 --- a/src/components/WizardHint/index.tsx +++ b/src/components/WizardHint/index.tsx @@ -1,16 +1,19 @@ import React from 'react' -import { IconX } from '@posthog/icons' +import { IconX, IconChevronDown } from '@posthog/icons' import CloudinaryImage from 'components/CloudinaryImage' import WizardCommand from 'components/WizardCommand' +const HEDGEHOG_SRC = 'https://res.cloudinary.com/dmukukwp6/image/upload/wizard_3f8bb7a240.png' + /** - * Dismissible agent-flavored nudge that pushes a `npx @posthog/wizard ` CLI flow as the + * Collapsible agent-flavored nudge that pushes a `npx @posthog/wizard ` CLI flow as the * automated alternative to manual setup. Visual design matches [`WizardCTA`](../WizardCTA). * - * Dismissal persists in localStorage under `${dismissKey}-dismissed`. theme-init.js reads that key - * before first paint and sets the same class on ; a per-variant rule in global.css hides the - * hint (matched by the `dismissKey` class on the wrapper). Adding a new variant means wiring the - * new key in both places — see the README. + * Collapsing persists in localStorage under `${dismissKey}-dismissed`. theme-init.js reads that key + * before first paint and sets the same class on ; per-variant rules in global.css swap the + * full banner for the slim re-expandable bar (both are always rendered, so there is no hydration + * flash in either state). Adding a new variant means wiring the new key in both places — see the + * README. */ export default function WizardHint({ command, @@ -23,51 +26,69 @@ export default function WizardHint({ command: string title: string subtitle: string - /** Base name for the dismissal localStorage key, class, and wrapper class */ + /** Base name for the collapse localStorage key, class, and wrapper class */ dismissKey: string className?: string }): JSX.Element { - const handleDismiss = () => { + const handleCollapse = () => { localStorage.setItem(`${dismissKey}-dismissed`, '1') document.documentElement.classList.add(`${dismissKey}-dismissed`) } + const handleExpand = () => { + localStorage.removeItem(`${dismissKey}-dismissed`) + document.documentElement.classList.remove(`${dismissKey}-dismissed`) + } + return ( -
+
+
+ +
+ + +
+
+

{title}

+

{subtitle}

+ +
+
+ PostHog Wizard hedgehog +
+
+
+
+ {/* Slim bar shown in place of the banner once collapsed. Hidden by default and toggled + to flex by the global.css rules — no `flex` utility here or it would always show. */} -
- - -
-
-

{title}

-

{subtitle}

- -
-
- PostHog Wizard hedgehog -
-
-
) } diff --git a/src/styles/global.css b/src/styles/global.css index 150ab4321deb..218fc7702e00 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -3152,11 +3152,18 @@ div[data-radix-popper-content-wrapper] { } } -/* Set on by theme-init.js before paint when the hint was previously dismissed. */ -html.warehouse-wizard-hint-dismissed .warehouse-wizard-hint { +/* Set on by theme-init.js before paint when the hint was previously collapsed. + Collapsing swaps the WizardHint's full banner for its slim re-expandable bar. */ +.wizard-hint-collapsed { display: none; } -html.ai-observability-wizard-hint-dismissed .ai-observability-wizard-hint { +html.warehouse-wizard-hint-dismissed .warehouse-wizard-hint .wizard-hint-full, +html.ai-observability-wizard-hint-dismissed .ai-observability-wizard-hint .wizard-hint-full { display: none; } + +html.warehouse-wizard-hint-dismissed .warehouse-wizard-hint .wizard-hint-collapsed, +html.ai-observability-wizard-hint-dismissed .ai-observability-wizard-hint .wizard-hint-collapsed { + display: flex; +}