-
Notifications
You must be signed in to change notification settings - Fork 159
feat: push replay and person links into external integrations #1980
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5e9d9bc
3d6c8b1
8e460d7
d2ed6cf
a3ffbb7
82a35fa
8438c4b
47ba0b5
4ca221e
898c756
09048dd
e883062
1b70ce9
9345f34
48320e2
3cf4282
f033160
e7690b3
1555ddf
7ac4d53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import Script from 'next/script' | ||
|
||
export default function ExternalChat() { | ||
return ( | ||
<div> | ||
<h1>ExternalChat</h1> | ||
<p>This is a page for testing external chat widgets</p> | ||
|
||
{/* Intercom Settings Script */} | ||
<Script id="intercom-settings" strategy="beforeInteractive"> | ||
{` | ||
window.intercomSettings = { | ||
api_base: "https://api-iam.intercom.io", | ||
app_id: "cviln1h1", | ||
}; | ||
`} | ||
</Script> | ||
|
||
{/* Intercom Widget Script */} | ||
<Script id="intercom-widget" strategy="afterInteractive"> | ||
{` | ||
(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/cviln1h1';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})(); | ||
`} | ||
</Script> | ||
|
||
{/* Crisp chat Script */} | ||
<Script id="crisp-chat" strategy="afterInteractive"> | ||
{` | ||
window.$crisp=[]; | ||
window.CRISP_WEBSITE_ID="8a81621c-0ed1-4d1f-b552-9404db8effd5"; | ||
(function(){ | ||
d = document; | ||
s = d.createElement("script"); | ||
s.src = "https://client.crisp.chat/l.js"; | ||
s.async = 1; | ||
d.getElementsByTagName("head")[0].appendChild(s); | ||
})(); | ||
`} | ||
</Script> | ||
</div> | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { PostHog } from '../posthog-core' | ||
import { assignableWindow } from '../utils/globals' | ||
import { createLogger } from '../utils/logger' | ||
|
||
const logger = createLogger('[PostHog Crisp Chat]') | ||
|
||
const reportedSessionIds = new Set<string>() | ||
|
||
assignableWindow.__PosthogExtensions__ = assignableWindow.__PosthogExtensions__ || {} | ||
assignableWindow.__PosthogExtensions__.integrations = assignableWindow.__PosthogExtensions__.integrations || {} | ||
assignableWindow.__PosthogExtensions__.integrations.crispChat = { | ||
start: (posthog: PostHog) => { | ||
if (!posthog.config.integrations?.crispChat) { | ||
return | ||
} | ||
|
||
const crispChat = (assignableWindow as any).$crisp | ||
if (!crispChat) { | ||
logger.warn(' Crisp Chat not found while initializing the integration') | ||
return | ||
} | ||
|
||
const updateCrispChat = () => { | ||
const replayUrl = posthog.get_session_replay_url() | ||
const personUrl = posthog.requestRouter.endpointFor( | ||
'ui', | ||
`/project/${posthog.config.token}/person/${posthog.get_distinct_id()}` | ||
) | ||
|
||
crispChat.push([ | ||
'set', | ||
'session:data', | ||
[ | ||
[ | ||
['posthogSessionURL', replayUrl], | ||
['posthogPersonURL', personUrl], | ||
], | ||
], | ||
]) | ||
} | ||
|
||
// this is called immediately if there's a session id | ||
// and then again whenever the session id changes | ||
posthog.onSessionId((sessionId) => { | ||
if (!reportedSessionIds.has(sessionId)) { | ||
updateCrispChat() | ||
reportedSessionIds.add(sessionId) | ||
} | ||
}) | ||
|
||
logger.info('integration started') | ||
}, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { PostHog } from '../posthog-core' | ||
import { assignableWindow } from '../utils/globals' | ||
import { createLogger } from '../utils/logger' | ||
|
||
const logger = createLogger('[PostHog Intercom integration]') | ||
|
||
const reportedSessionIds = new Set<string>() | ||
|
||
assignableWindow.__PosthogExtensions__ = assignableWindow.__PosthogExtensions__ || {} | ||
assignableWindow.__PosthogExtensions__.integrations = assignableWindow.__PosthogExtensions__.integrations || {} | ||
assignableWindow.__PosthogExtensions__.integrations.intercom = { | ||
start: (posthog: PostHog) => { | ||
if (!posthog.config.integrations?.intercom) { | ||
return | ||
} | ||
|
||
const intercom = (assignableWindow as any).Intercom | ||
if (!intercom) { | ||
logger.warn(' Intercom not found while initializing the integration') | ||
return | ||
} | ||
|
||
const updateIntercom = () => { | ||
const replayUrl = posthog.get_session_replay_url() | ||
const personUrl = posthog.requestRouter.endpointFor( | ||
'ui', | ||
`/project/${posthog.config.token}/person/${posthog.get_distinct_id()}` | ||
) | ||
|
||
intercom('update', { | ||
latestPosthogReplayURL: replayUrl, | ||
latestPosthogPersonURL: personUrl, | ||
}) | ||
intercom('trackEvent', 'posthog:sessionInfo', { replayUrl, personUrl }) | ||
} | ||
|
||
// this is called immediately if there's a session id | ||
// and then again whenever the session id changes | ||
posthog.onSessionId((sessionId) => { | ||
if (!reportedSessionIds.has(sessionId)) { | ||
updateIntercom() | ||
reportedSessionIds.add(sessionId) | ||
} | ||
}) | ||
|
||
logger.info('integration started') | ||
}, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { PostHog } from '../posthog-core' | ||
import { ExternalIntegrationKind } from '../types' | ||
import { assignableWindow, ExternalExtensionKind } from '../utils/globals' | ||
import { createLogger } from '../utils/logger' | ||
|
||
const logger = createLogger('[PostHog ExternalIntegrations]') | ||
|
||
const MAPPED_INTEGRATIONS: Record<ExternalIntegrationKind, ExternalExtensionKind> = { | ||
intercom: 'intercom-integration', | ||
crispChat: 'crisp-chat-integration', | ||
} | ||
|
||
export class ExternalIntegrations { | ||
constructor(private readonly _instance: PostHog) {} | ||
|
||
private _loadScript(name: ExternalExtensionKind, cb: () => void): void { | ||
assignableWindow.__PosthogExtensions__?.loadExternalDependency?.(this._instance, name, (err) => { | ||
if (err) { | ||
return logger.error('failed to load script', err) | ||
} | ||
cb() | ||
}) | ||
} | ||
|
||
public startIfEnabledOrStop() { | ||
for (const [key, value] of Object.entries(this._instance.config.integrations ?? {})) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ie11 giving JavaScript error details: but we polyfill it https://github.com/PostHog/posthog-js/pull/1980/files#diff-001e332a80712cf09955389a80c7dd2eaf800699391a5145792eb41337dd18eeR8 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah! This is dangnammit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, before this polyfill we had dist/array.full.es5.js | 300 kB | +914 B (+0.31%) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dist/array.full.es5.js | 301 kB | +1.73 kB (+0.58%) not too bad... assuming it works |
||
if (value && !assignableWindow.__PosthogExtensions__?.integrations?.[key as ExternalIntegrationKind]) { | ||
this._loadScript(MAPPED_INTEGRATIONS[key as ExternalIntegrationKind], () => { | ||
assignableWindow.__PosthogExtensions__?.integrations?.[key as ExternalIntegrationKind]?.start( | ||
this._instance | ||
) | ||
}) | ||
} | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.