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

  1. Go to Support in PostHog and click Settings
  2. Click Enable conversations
  3. Go to the In-app widget section and enable it
  4. Configure your settings
  5. 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:

SettingDescriptionOptionsDefault
Enable widgetShow the chat widget on your sitetrue, falsefalse
Button colorPrimary color for the widget (hex)Any hex color#5375ff
Widget positionPosition of the widget on screenbottom_right, bottom_left, top_right, top_leftbottom_right
Greeting messageWelcome text shown when widget opensAny string"Hi! How can we help?"
Allowed domainsRestrict which domains can show the widgetArray of domain strings[] (all domains)

Identification form

You can optionally require users to identify themselves before starting a conversation:

SettingDescriptionDefault
Require emailUsers must enter their email to start chattingfalse
Collect nameAdditionally collect a namefalse
Form titleHeading shown on the identification form"Before we start..."
Form descriptionSubtext 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:

JavaScript
// Configured in PostHog settings
domains: [
"example.com", // Exact match
"*.example.com", // Wildcard: matches sub.example.com
"https://app.example.com" // With protocol (protocol is stripped)
]

If domains is empty or not set, the widget shows on all domains.

Show and hide the widget

Use the JavaScript API to programmatically show or hide the widget:

JavaScript
// Show the widget (renders it if not already rendered)
posthog.conversations.show()
// Hide and remove the widget from DOM
posthog.conversations.hide()
// Check if widget is currently visible
const isVisible = posthog.conversations.isVisible()

This is useful for:

  • Showing the widget only on certain pages
  • Triggering the widget from a custom button
  • Hiding the widget during specific user flows

Disable the widget

You can disable conversations entirely via the PostHog init config:

JavaScript
posthog.init('<ph_project_token>', {
disable_conversations: true // Prevents loading the conversations module
})

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.

  1. Click Recover your tickets in the ticket list
  2. Enter the email address used in previous conversations
  3. A recovery link is sent to that email and expires in one hour
  4. 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.

setIdentity vs identify

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

  1. Your server computes an HMAC-SHA256 hash of the user's distinct_id using your team's secret_api_token
  2. You pass this hash along with the distinct_id to the widget
  3. The widget API verifies the signature and uses the distinct_id for ticket lookup instead of the browser session

With identity verification enabled, users see all their tickets on any browser or device.

Server-side implementation

Generate the identity hash on your backend. Never expose your secret_api_token in client-side code.

import hmac
import hashlib
def compute_identity_hash(distinct_id: str, secret_api_token: str) -> str:
return hmac.new(
secret_api_token.encode(),
distinct_id.encode(),
hashlib.sha256,
).hexdigest()

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:

JavaScript
posthog.init('<ph_project_token>', {
api_host: 'https://us.i.posthog.com',
identity_distinct_id: 'user_123', // From your auth system
identity_hash: 'a1b2c3d4e5f6...', // HMAC hash from your server
})

Option 2: Set identity after login

For single-page apps – or when the user logs in after page load – call setIdentity():

JavaScript
// After user logs in, your server returns the hash
const identityHash = await fetchIdentityHashFromServer(userId)
// Pass it to the SDK
posthog.setIdentity('user_123', identityHash)

Clear identity on logout

When a user logs out, clear their identity so the widget falls back to session-based access:

JavaScript
posthog.clearIdentity()
Keep your secret API token secure

Your secret_api_token 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

ScenarioRecommended approach
Logged-in usersUse identity verification for seamless cross-device access
Anonymous visitorsUse the default widget session (no setup required)
Mixed audienceUse identity verification when users are logged in, fall back to widget session for anonymous users

If your team doesn't have a secret_api_token configured, identity verification is ignored and the widget falls back to session-based access control.

Notifications

Get notified when new tickets arrive, by email or in your browser.

Email notifications

Configure your team to receive email alerts when new tickets arrive.

  1. Go to Settings > Support in PostHog
  2. Find the Email notifications section
  3. 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.

Use Workflows for advanced notifications

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.

Browser notifications

Individual team members can enable browser notifications for new ticket activity.

  1. Go to Support in PostHog
  2. 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:

  1. Go to Support > Settings
  2. Click Regenerate token
Resetting stops active chats

Resetting the token stops current chats. Users need to refresh the page to reconnect with the new token.

Community questions

Was this page useful?