Skip to content

Commit c17cb55

Browse files
authored
fix(extension): isolate embedded pages from tracking (#9480)
1 parent 875f40a commit c17cb55

4 files changed

Lines changed: 60 additions & 3 deletions

File tree

‎apps/sim/lib/consent/google-context.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { GOOGLE_CLICK_ID_PARAMETERS, UTM_PARAMETERS } from '@/lib/analytics/campaign-parameters'
2-
import { isNoindexPath } from '@/lib/navigation/paths'
2+
import { isNoindexPath, isPathOrDescendant } from '@/lib/navigation/paths'
33

44
const GOOGLE_ANALYTICS_ORIGINS = new Set(['https://sim.ai', 'https://www.sim.ai'])
55

@@ -51,6 +51,7 @@ export function getGooglePageLocation(value: string): string | undefined {
5151
try {
5252
const url = new URL(value)
5353
if (!GOOGLE_ANALYTICS_ORIGINS.has(url.origin)) return undefined
54+
if (isPathOrDescendant(decodeURIComponent(url.pathname), '/extension')) return undefined
5455

5556
const campaign = new URLSearchParams()
5657
for (const parameter of GOOGLE_CAMPAIGN_PARAMETERS) {

‎apps/sim/lib/consent/scripts.test.ts‎

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
trackGoogleEvent,
99
trackGooglePageView,
1010
} from '@/lib/analytics/google'
11-
import { getGooglePageLocation } from '@/lib/consent/google-context'
11+
import { getGooglePageLocation, updateGooglePageContext } from '@/lib/consent/google-context'
1212
import {
1313
type ConsentScriptCallbackInfo,
1414
GOOGLE_ADS_ID,
@@ -101,6 +101,53 @@ describe('consent scripts', () => {
101101
expect(getGooglePageLocation('https://www.sim.ai/library')).toBeUndefined()
102102
})
103103

104+
it.each(['/extension', '/extension/o/org-id', '/%65xtension/workspace-id'])(
105+
'does not register third-party tracking scripts for %s',
106+
(path) => {
107+
window.history.replaceState({}, '', path)
108+
109+
expect(getGlobalConsentScripts()).toEqual([])
110+
expect(getGooglePageLocation(window.location.href)).toBeUndefined()
111+
}
112+
)
113+
114+
it('stops Google events when navigating into the extension and resumes on public pages', () => {
115+
window.history.replaceState({}, '', '/library')
116+
getGlobalConsentScripts()[0]?.onBeforeLoad?.(CALLBACK_INFO)
117+
window.dataLayer = []
118+
window.history.pushState({}, '', '/extension/o/private-org?utm_source=google')
119+
120+
trackGooglePageView('/extension/o/private-org')
121+
trackGoogleEvent('sign_up', { method: 'email' })
122+
trackGoogleAdsConversion('demo_booked')
123+
124+
expect(window.dataLayer).toEqual([])
125+
126+
window.history.pushState({}, '', '/extension-guide')
127+
trackGooglePageView('/extension-guide')
128+
expect(window.dataLayer).toContainEqual([
129+
'event',
130+
'page_view',
131+
{
132+
page_path: '/extension-guide',
133+
page_location: 'https://www.sim.ai/extension-guide',
134+
send_to: GOOGLE_ANALYTICS_ID,
135+
},
136+
])
137+
})
138+
139+
it('removes extension scope IDs from referrals to public pages', () => {
140+
window.history.replaceState({}, '', '/library')
141+
getGlobalConsentScripts()[0]?.onBeforeLoad?.(CALLBACK_INFO)
142+
143+
updateGooglePageContext(window.location.href, 'https://www.sim.ai/extension/o/private-org')
144+
145+
expect(window.dataLayer.at(-1)).toEqual([
146+
'set',
147+
expect.objectContaining({ page_referrer: 'https://www.sim.ai/extension' }),
148+
])
149+
})
150+
104151
it('keeps supported campaign parameters and removes unknown parameters and fragments', () => {
105152
expect(
106153
getGooglePageLocation(

‎apps/sim/lib/consent/scripts.ts‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { gtag } from '@c15t/scripts/google-tag'
33
import { xPixel } from '@c15t/scripts/x-pixel'
44
import { FREEBUFF_TAG_SRC, installFreebuffStub } from '@/lib/analytics/freebuff'
55
import { getGooglePageLocation, updateGooglePageContext } from '@/lib/consent/google-context'
6+
import { isPathOrDescendant } from '@/lib/navigation/paths'
67

78
export const GOOGLE_ANALYTICS_ID = 'G-QB9D67TBHR' as const
89

@@ -67,8 +68,15 @@ const GLOBAL_CONSENT_SCRIPTS = [
6768
},
6869
] as const
6970

70-
/** Registers Google's shared destination only on Sim's actual production origins. */
71+
/** Excludes embedded extension pages and restricts Google's loader to production origins. */
7172
export function getGlobalConsentScripts() {
73+
if (typeof window !== 'undefined') {
74+
try {
75+
if (isPathOrDescendant(decodeURIComponent(window.location.pathname), '/extension')) return []
76+
} catch {
77+
return []
78+
}
79+
}
7280
const googleEnabled =
7381
typeof window !== 'undefined' && getGooglePageLocation(window.location.href) !== undefined
7482
return GLOBAL_CONSENT_SCRIPTS.filter((script) => script.id !== 'gtag' || googleEnabled)

‎apps/sim/lib/navigation/paths.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export function isAppSurfacePath(pathname: string): boolean {
8181
*/
8282
const NOINDEX_PATH_ROOTS = [
8383
'/chat',
84+
'/extension',
8485
'/resume',
8586
'/invite',
8687
'/unsubscribe',

0 commit comments

Comments
 (0)