Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/customerio-messaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Embedded Cloud continues to own its existing integration.
The default public browser keys in `src/shared/customerIo.ts` use the existing
Cloud Customer.io source. Identity is the same Firebase UID used on Cloud.
Desktop sends `identify` with the selected locale, a page named
**`desktop/local-workflow`**, and the SDK's delivery/interaction metrics. Page
**`desktop/comfyui`**, and the SDK's delivery/interaction metrics. Page
properties also use this synthetic target, rather than the local workflow URL.

Configure Desktop messages to match that page name. Audit campaigns with no page
Expand Down
8 changes: 5 additions & 3 deletions e2e/customerio.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const identity: CustomerIoSession = {
userId: 'desktop-test-user',
locale: 'ja',
writeKey: 'test-write-key',
siteId: 'test-site'
siteId: 'test-site',
page: 'desktop/comfyui'
}

/** Exercise the shipped preload and real SDK without a ComfyUI install or vendor traffic. */
Expand Down Expand Up @@ -116,7 +117,7 @@ document.getElementById('close').onclick = () => parent.postMessage({gist:{insta
properties: {
gist: {
campaignId: `fixture-delivery-${delivery}`,
routeRuleWeb: 'desktop/local-workflow',
routeRuleWeb: 'desktop/comfyui',
persistent:
request.headers()['x-gist-encoded-user-token'] ===
Buffer.from('second-test-user').toString('base64')
Expand Down Expand Up @@ -198,7 +199,7 @@ document.getElementById('close').onclick = () => parent.postMessage({gist:{insta
const events = requests.filter(({ url }) =>
/^https:\/\/cdp\.customer\.io\/v1\/[ipt]$/.test(url)
)
expect(events.some(({ body }) => body?.includes('"name":"desktop/local-workflow"'))).toBe(true)
expect(events.some(({ body }) => body?.includes('"name":"desktop/comfyui"'))).toBe(true)
expect(
events.every(
({ body }) => !/private-workflow|private-query|private-referrer/.test(body ?? '')
Expand All @@ -209,6 +210,7 @@ document.getElementById('close').onclick = () => parent.postMessage({gist:{insta
for (const { body } of pages) {
expect(JSON.parse(body!).properties).toMatchObject({ search: '', referrer: '' })
}

const queues = requests.filter(({ url }) => url.includes('/api/v4/users'))
expect(queues.length).toBeGreaterThanOrEqual(2)
expect(queues.every(({ headers }) => headers['x-cio-site-id'] === identity.siteId)).toBe(true)
Expand Down
2 changes: 2 additions & 0 deletions src/main/lib/customerIoMessaging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { app, ipcMain, shell, type IpcMainEvent, type WebContents } from 'electr
import type { ComfyWindowEntry } from '../host/registry'
import {
CUSTOMER_IO_DEFAULTS,
CUSTOMER_IO_PAGES,
CUSTOMER_IO_ACTION,
CUSTOMER_IO_READY,
CUSTOMER_IO_STATE
Expand Down Expand Up @@ -42,6 +43,7 @@ export function customerIoSession(entry: ComfyWindowEntry): CustomerIoSession |
if (!userId) return null
return {
userId,
page: CUSTOMER_IO_PAGES.comfyui,
locale: i18n.getLocale(),
writeKey: process.env.COMFY_CUSTOMER_IO_WRITE_KEY || CUSTOMER_IO_DEFAULTS.writeKey,
siteId: process.env.COMFY_CUSTOMER_IO_SITE_ID || CUSTOMER_IO_DEFAULTS.siteId
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/customerIo/controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const session: CustomerIoSession = {
userId: 'user-a',
locale: 'en',
writeKey: 'test',
siteId: 'test'
siteId: 'test',
page: 'desktop/comfyui'
}
function client(): MessagingClient {
return {
Expand Down Expand Up @@ -35,6 +36,7 @@ describe('Desktop messaging lifecycle', () => {
await controller.update({ ...session })
expect(load).toHaveBeenCalledTimes(1)
expect(sdk.identify).toHaveBeenCalledExactlyOnceWith(session)
expect(sdk.page).toHaveBeenCalledExactlyOnceWith(session)
expect(vi.mocked(sdk.identify).mock.invocationCallOrder[0]).toBeLessThan(
vi.mocked(sdk.page).mock.invocationCallOrder[0]!
)
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/customerIo/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { CustomerIoSession } from '../../../shared/customerIo'

export interface MessagingClient {
identify(session: CustomerIoSession): Promise<void>
page(): Promise<void>
page(session: CustomerIoSession): Promise<void>
reset(): Promise<void>
dismiss(): void
}
Expand Down Expand Up @@ -59,7 +59,7 @@ export function createMessagingController(
await bounded(client.identify(session))
if (revision !== version) return
identified = session
await bounded(client.page())
await bounded(client.page(session))
})
.catch((error: unknown) => {
client?.dismiss()
Expand Down
15 changes: 7 additions & 8 deletions src/renderer/src/customerIo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import Gist from 'customerio-gist-web'
import type { CustomerIoSession } from '../../../shared/customerIo'
import { createMessagingController } from './controller'

const PAGE = 'desktop/local-workflow'

const controller = createMessagingController(async (session, currentSession) => {
const analytics = AnalyticsBrowser.load(
{ writeKey: session.writeKey },
Expand All @@ -24,12 +22,13 @@ const controller = createMessagingController(async (session, currentSession) =>
await analytics.addSourceMiddleware(({ payload, next }) => {
const current = currentSession()
if (!current || payload.obj.userId !== current.userId) return
if (payload.obj.type === 'page' && payload.obj.name !== current.page) return
// A desktop file path or local workflow URL is not a useful campaign page.
payload.obj.context = {
...payload.obj.context,
page: {
path: PAGE,
url: PAGE,
path: current.page,
url: current.page,
title: 'ComfyUI Desktop',
referrer: '',
search: ''
Expand Down Expand Up @@ -64,10 +63,10 @@ const controller = createMessagingController(async (session, currentSession) =>
Gist.setUserLocale(identity.locale)
await analytics.identify(identity.userId, { locale: identity.locale })
},
page: async () => {
await analytics.page(PAGE, {
url: PAGE,
path: PAGE,
page: async ({ page }) => {
await analytics.page(page, {
url: page,
path: page,
title: 'ComfyUI Desktop',
search: '',
referrer: ''
Expand Down
8 changes: 8 additions & 0 deletions src/shared/customerIo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@ export const CUSTOMER_IO_READY = 'customerio:ready'
export const CUSTOMER_IO_STATE = 'customerio:state'
export const CUSTOMER_IO_ACTION = 'customerio:action'

/** Stable page names used by Customer.io's in-app page rules. */
export const CUSTOMER_IO_PAGES = {
comfyui: 'desktop/comfyui',
launcher: 'desktop/launcher'
} as const
export type CustomerIoPage = (typeof CUSTOMER_IO_PAGES)[keyof typeof CUSTOMER_IO_PAGES]

export interface CustomerIoSession {
userId: string
locale: string
writeKey: string
siteId: string
page: CustomerIoPage
}
Loading