Set up the widget
Contents
The Support widget is a chat interface that appears on your website so your customers can start conversations with your team. It loads automatically when enabled and captures session context for each ticket.

Enable the widget
- Go to Support in PostHog and click Settings
- Click Enable support
- Go to the In-app widget section and enable it
- Configure your settings
- Click Save
The widget appears as a floating button on your site. By default it appears in the bottom-right corner, but you can customize its position in the settings.
Configuration options
Configure these settings in the In-app widget section of Support settings:
| Setting | Description | Options | Default |
|---|---|---|---|
| Enable widget | Show the chat widget on your site | true, false | false |
| Button color | Primary color for the widget (hex). A theme overrides it | Any hex color | #5375ff |
| Widget position | Position of the widget on screen | bottom_right, bottom_left, top_right, top_left | bottom_right |
| Greeting message | Welcome text shown when widget opens | Any string | "Hi! How can we help?" |
| Allowed domains | Restrict which domains can show the widget | Array of domain strings | [] (all domains) |

Identification form
You can optionally require users to identify themselves before starting a conversation:
| Setting | Description | Default |
|---|---|---|
| Require email | Users must enter their email to start chatting | false |
| Collect name | Additionally collect a name | false |
| Form title | Heading shown on the identification form | "Before we start..." |
| Form description | Subtext shown below the title | "Please provide your details so we can help you better." |

When enabled, the form appears before they can send their first message. PostHog uses this information to link the ticket to a person.
Customize widget behavior
Control where the widget loads and how it appears.
Restrict domains
You can restrict which domains the widget appears on for security:

If domains is empty or not set, the widget shows on all domains.
Show and hide the widget
show() adds the widget, including the launcher button. hide() removes it from the page. show() does nothing until the widget bundle has loaded. These methods are part of the JavaScript API.
Use this to show the widget only on certain pages, or to hide it during a flow such as checkout. To open the chat from a button in your own UI, use open().
Open and close the chat panel
open() and close() control the chat panel. The launcher stays on the page. open() renders the widget first when it is not already there.
If you call open() or close() before the widget bundle has loaded, the last call runs once the bundle loads. A hide() call cancels an open() that is still waiting. open() does nothing on a domain that is not in Allowed domains. These methods need posthog-js 1.442.0 or later.
Theme the widget
Button color in Support settings sets the primary color. To match the rest of your site, including dark mode, fonts, corner radius, and shadows, pass a theme when you initialize PostHog, or call setTheme() later.
Theming needs posthog-js 1.444.0 or later.
colorScheme picks the palette:
lightis the default.darkuses the built-in dark colors.autofollows the visitor'sprefers-color-scheme.
The top-level colors apply to the light scheme only. dark holds the colors used when the dark scheme is active, so set background, text, and the other colors there for dark mode. A color you leave unset in dark falls back to the built-in dark color. primary and primaryText are the exception: they keep the light values until you set them under dark.
setTheme() merges the object you pass over the current theme. The dark object merges the same way, so a later call can change one dark color without clearing the others. It is safe to call before the widget loads, and posthog.reset() keeps the theme.
You can set the same values in your own stylesheet. The widget reads them as CSS custom properties on #ph-conversations-widget-container. A rule that selects #ph-conversations-widget-container overrides the theme from the SDK.
Values apply in this order: built-in defaults, the Button color from Support settings, the theme in posthog.init(), setTheme(), then your CSS.
| Theme option | CSS variable | What it sets |
|---|---|---|
colorScheme | – | light, dark, or auto |
primary | --ph-conv-primary | Launcher, header, customer messages, and buttons. Overrides Button color. |
primaryText | --ph-conv-on-primary | Text and icons on primary. When this is unset, the widget picks black or white for contrast if primary is a hex color, and white otherwise. |
background | --ph-conv-bg | Window, message list, and input background |
surface | --ph-conv-surface | Identification form, unread tickets, and code blocks |
text | --ph-conv-text | Main text |
mutedText | --ph-conv-muted | Timestamps, author names, and descriptions |
border | --ph-conv-border | Borders and dividers |
agentBubble | --ph-conv-agent-bubble | Messages from your team |
fontFamily | --ph-conv-font | Font family |
borderRadius | --ph-conv-radius | Corner radius of the chat window, for example 16px |
launcherShadow | --ph-conv-launcher-shadow | CSS filter on the launcher, for example none |
windowShadow | --ph-conv-window-shadow | CSS box-shadow of the chat window |
Color options take any CSS color. fontFamily, borderRadius, launcherShadow, and windowShadow take the CSS value for that property. The widget ignores a value that contains {, }, ;, <, or >, and logs a warning.
Disable the widget
You can disable conversations entirely via the PostHog init config:
This is different from hiding the widget – it completely disables the feature.
Recover tickets across browsers
Support tickets are tied to the browser session by default. If a user switches browsers or clears their storage, they won't see their previous tickets. The widget includes a Recover your tickets link to handle this.
- Click Recover your tickets in the ticket list
- Enter the email address used in previous conversations
- A recovery link is sent to that email and expires in one hour
- Click the link to open the widget and restore tickets in the new browser
If the page URL contains a ph_conv_restore query parameter from the recovery link, tickets are automatically restored on page load. The parameter is removed from the URL after processing.
Identity verification
If your app has logged-in users, identity verification works better than email-based recovery. You sign the user's distinct ID on your server, and tickets persist across browsers and devices automatically – no user action required.
posthog.setIdentity() and posthog.identify() are different methods:
identify()links events to a user for analytics. It creates person profiles and merges anonymous events with identified ones. See identifying users.setIdentity()verifies ticket ownership for Support. It uses HMAC signing to prove the user is who they claim to be, enabling cross-browser ticket access.
You typically call both: identify() for analytics tracking, and setIdentity() for secure ticket access.
How it works
- Your server computes an HMAC-SHA256 hash of the user's
distinct_idusing your Identity verification secret from Support settings - You pass this hash along with the
distinct_idto the widget - The widget API verifies the signature and uses the
distinct_idfor ticket lookup instead of the browser session
With identity verification enabled, users see all their tickets on any browser or device.
Find your identity verification secret
- Go to Support > Settings
- Open the Identity verification secret section. If it is empty, click the button next to it to generate a secret
- Copy the key. Use it only on your server
The secret lives at Support > Settings.
If you sign the hash with a key that does not work, the widget API answers 403 Forbidden and gives no detail about the cause. The response is the same for a wrong key, a bad signature, and a project with no key, so that the API tells anonymous callers nothing about your setup. If GET /widget/tickets or POST /widget/message answers 403, check your key first. See troubleshooting.
When you rotate the key, PostHog keeps the previous key verifying for 48 hours. Update your server-side code within that window. After 48 hours, the previous key expires on its own. No manual deletion is needed. If the previous key may be compromised, click Expire now in the settings banner to stop it verifying immediately.
Server-side implementation
Generate the identity hash on your backend. Never expose the identity verification secret in client-side code.
Pass identity to the widget
Once you've computed the hash on your server, pass it to your frontend and set it on the PostHog SDK.
Option 1: Set identity at initialization
If you know the user's identity when PostHog initializes, such as on a server-rendered page, pass it in the init config:
Option 2: Set identity after login
For single-page apps – or when the user logs in after page load – call setIdentity():
Clear identity on logout
When a user logs out, clear their identity so the widget falls back to session-based access:
Your identity verification secret must never be exposed in client-side code. Always compute the identity hash on your server and pass only the hash to the frontend.
When to use identity verification
| Scenario | Recommended approach |
|---|---|
| Logged-in users | Use identity verification for seamless cross-device access |
| Anonymous visitors | Use the default widget session (no setup required) |
| Mixed audience | Use identity verification when users are logged in, fall back to widget session for anonymous users |
If your project has no identity verification secret, requests that carry identity fields get 403 Forbidden. Generate one in Support settings. Requests without identity fields keep using the browser session.
Notifications
Get notified when new tickets arrive, by email or in your browser.
For more control over notifications – like sending alerts only for high-priority tickets, routing to specific Slack channels, or notifying different teams based on tags – use workflow automation. Workflows let you trigger Slack messages, webhooks, and more based on any ticket event.
Email notifications
Configure your team to receive email alerts when new tickets arrive.
- Go to Support > Settings in PostHog
- Open the Notifications tab and find Email notifications
- Select team members who should receive alerts
Emails include:
- Team name
- Ticket number
- First message preview
- Direct link to the ticket
Recipients must have access to the team to receive notifications.
Browser notifications
Individual team members can enable browser notifications for new ticket activity.
- Go to Support in PostHog
- Enable Browser notifications in the notification settings

When enabled, a desktop notification appears when the unread ticket count increases. This works independently of email notifications – you can use one or both.
Public token
The widget uses a public token for authentication. This token is automatically generated and shown in your Support settings. It's safe to expose in client-side code.
If you need to reset the token:
- Go to Support > Settings
- Click Regenerate token
Resetting the token stops current chats. Users need to refresh the page to reconnect with the new token.





