diff --git a/playground/nextjs/pages/index.tsx b/playground/nextjs/pages/index.tsx index 3c3a06cbb..f2a72d5fb 100644 --- a/playground/nextjs/pages/index.tsx +++ b/playground/nextjs/pages/index.tsx @@ -1,6 +1,9 @@ +/* eslint-disable no-console */ import { useActiveFeatureFlags, usePostHog } from 'posthog-js/react' -import React, { useEffect, useState } from 'react' -import { PERSON_PROCESSING_MODE, cookieConsentGiven } from '@/src/posthog' +import { useEffect, useState } from 'react' +import { cookieConsentGiven, PERSON_PROCESSING_MODE } from '@/src/posthog' +import { setAllPersonProfilePropertiesAsPersonPropertiesForFlags } from 'posthog-js/lib/src/customizations/setAllPersonProfilePropertiesAsPersonPropertiesForFlags' +import { STORED_PERSON_PROPERTIES_KEY } from '../../../src/constants' export default function Home() { const posthog = usePostHog() @@ -40,6 +43,15 @@ export default function Home() { Autocapture a > span + External link {isClient && typeof window !== 'undefined' && process.env.NEXT_PUBLIC_CROSSDOMAIN && ( { + const orig = jest.requireActual('../../utils/globals') + const mockURLGetter = jest.fn() + const mockReferrerGetter = jest.fn() + return { + ...orig, + mockURLGetter, + mockReferrerGetter, + userAgent: 'Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0', + navigator: { + vendor: '', + }, + document: { + ...orig.document, + createElement: (...args: any[]) => orig.document.createElement(...args), + get referrer() { + return mockReferrerGetter() + }, + get URL() { + return mockURLGetter() + }, + }, + get location() { + const url = mockURLGetter() + return { + href: url, + toString: () => url, + } + }, + } +}) + +// eslint-disable-next-line @typescript-eslint/no-require-imports +const { mockURLGetter, mockReferrerGetter } = require('../../utils/globals') + +describe('setAllPersonPropertiesForFlags', () => { + beforeEach(() => { + mockReferrerGetter.mockReturnValue('https://referrer.com') + mockURLGetter.mockReturnValue('https://example.com?utm_source=foo') + }) + + it('should called setPersonPropertiesForFlags with all saved properties that are used for person properties', async () => { + // arrange + const token = uuidv7() + const posthog = await createPosthogInstance(token) + + // act + setAllPersonProfilePropertiesAsPersonPropertiesForFlags(posthog) + + // assert + expect(posthog.persistence?.props[STORED_PERSON_PROPERTIES_KEY]).toMatchInlineSnapshot(` + Object { + "$browser": "Mobile Safari", + "$browser_version": null, + "$current_url": "https://example.com?utm_source=foo", + "$device_type": "Mobile", + "$os": "Android", + "$os_version": "4.4.0", + "$referrer": "https://referrer.com", + "$referring_domain": "referrer.com", + "dclid": null, + "fbclid": null, + "gad_source": null, + "gbraid": null, + "gclid": null, + "gclsrc": null, + "igshid": null, + "li_fat_id": null, + "mc_cid": null, + "msclkid": null, + "rdt_cid": null, + "ttclid": null, + "twclid": null, + "utm_campaign": null, + "utm_content": null, + "utm_medium": null, + "utm_source": "foo", + "utm_term": null, + "wbraid": null, + } + `) + }) +}) diff --git a/src/config.ts b/src/config.ts index 3c4adce82..51ddf6941 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,10 +1,10 @@ -import { version } from '../package.json' +import packageInfo from '../package.json' // overridden in posthog-core, // e.g. Config.DEBUG = Config.DEBUG || instance.config.debug const Config = { DEBUG: false, - LIB_VERSION: version, + LIB_VERSION: packageInfo.version, } export default Config diff --git a/src/customizations/setAllPersonProfilePropertiesAsPersonPropertiesForFlags.ts b/src/customizations/setAllPersonProfilePropertiesAsPersonPropertiesForFlags.ts new file mode 100644 index 000000000..42b7f52f9 --- /dev/null +++ b/src/customizations/setAllPersonProfilePropertiesAsPersonPropertiesForFlags.ts @@ -0,0 +1,15 @@ +import { PostHog } from '../posthog-core' +import { CAMPAIGN_PARAMS, EVENT_TO_PERSON_PROPERTIES, Info } from '../utils/event-utils' +import { each, extend, includes } from '../utils' + +export const setAllPersonProfilePropertiesAsPersonPropertiesForFlags = (posthog: PostHog): void => { + const allProperties = extend({}, Info.properties(), Info.campaignParams(), Info.referrerInfo()) + const personProperties: Record = {} + each(allProperties, function (v, k: string) { + if (includes(CAMPAIGN_PARAMS, k) || includes(EVENT_TO_PERSON_PROPERTIES, k)) { + personProperties[k] = v + } + }) + + posthog.setPersonPropertiesForFlags(personProperties) +} diff --git a/src/utils/event-utils.ts b/src/utils/event-utils.ts index 3f12553a7..120b3f5ba 100644 --- a/src/utils/event-utils.ts +++ b/src/utils/event-utils.ts @@ -31,6 +31,25 @@ export const CAMPAIGN_PARAMS = [ 'rdt_cid', // reddit ] +export const EVENT_TO_PERSON_PROPERTIES = [ + // mobile params + '$app_build', + '$app_name', + '$app_namespace', + '$app_version', + // web params + '$browser', + '$browser_version', + '$device_type', + '$current_url', + '$pathname', + '$os', + '$os_name', // $os_name is a special case, it's treated as an alias of $os! + '$os_version', + '$referring_domain', + '$referrer', +] + export const Info = { campaignParams: function (customParams?: string[]): Record { if (!document) {