Skip to content

Commit

Permalink
Support loading analytics into a custom global variable when using sn…
Browse files Browse the repository at this point in the history
…ippet version 5.2.1+ (#1032)
  • Loading branch information
zikaari authored Feb 1, 2024
1 parent c302fea commit 5c1511f
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/kind-crabs-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@segment/analytics-next': minor
---

Support loading analytics into a custom global variable when using snippet version 5.2.1 or later
54 changes: 54 additions & 0 deletions packages/browser-integration-tests/src/custom-global-key.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { test, expect } from '@playwright/test'
import { standaloneMock } from './helpers/standalone-mock'
import { extractWriteKeyFromUrl } from './helpers/extract-writekey'
import { CDNSettingsBuilder } from '@internal/test-helpers'

test.describe('Segment with custom global key', () => {
test.beforeEach(standaloneMock)
test.beforeEach(async ({ context }) => {
await context.route(
'https://cdn.segment.com/v1/projects/*/settings',
(route, request) => {
if (request.method().toLowerCase() !== 'get') {
return route.continue()
}

const writeKey = extractWriteKeyFromUrl(request.url()) || 'writeKey'
return route.fulfill({
status: 200,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(new CDNSettingsBuilder({ writeKey }).build()),
})
}
)
})

test('supports using a custom global key', async ({ page }) => {
// Load analytics.js
await page.goto('/standalone-custom-key.html')
await page.evaluate(() => {
;(window as any).segment_analytics.track('track before load')
;(window as any).segment_analytics.load('fake-key')
})

const req = await page.waitForRequest('https://api.segment.io/v1/t')

// confirm that any events triggered before load have been sent
expect(req.postDataJSON().event).toBe('track before load')

const contextObj = await page.evaluate(() =>
(window as any).segment_analytics.track('track after load')
)

// confirm that any events triggered after load return a regular context object
expect(contextObj).toMatchObject(
expect.objectContaining({
attempts: expect.anything(),
event: expect.objectContaining({ event: 'track after load' }),
stats: expect.objectContaining({ metrics: expect.anything() }),
})
)
})
})
94 changes: 94 additions & 0 deletions packages/browser-integration-tests/standalone-custom-key.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<!DOCTYPE html>
<html>
<head>
<script>
!(function () {
var i = 'segment_analytics',
analytics = (window[i] = window[i] || [])
if (!analytics.initialize)
if (analytics.invoked)
window.console &&
console.error &&
console.error('Segment snippet included twice.')
else {
analytics.invoked = !0
analytics.methods = [
'trackSubmit',
'trackClick',
'trackLink',
'trackForm',
'pageview',
'identify',
'reset',
'group',
'track',
'ready',
'alias',
'debug',
'page',
'screen',
'once',
'off',
'on',
'addSourceMiddleware',
'addIntegrationMiddleware',
'setAnonymousId',
'addDestinationMiddleware',
'register',
]
analytics.factory = function (e) {
return function () {
if (window[i].initialized)
return window[i][e].apply(window[i], arguments)
var n = Array.prototype.slice.call(arguments)
if (
[
'track',
'screen',
'alias',
'group',
'page',
'identify',
].indexOf(e) > -1
) {
var c = document.querySelector("link[rel='canonical']")
n.push({
__t: 'bpc',
c: (c && c.getAttribute('href')) || void 0,
p: location.pathname,
u: location.href,
s: location.search,
t: document.title,
r: document.referrer,
})
}
n.unshift(e)
analytics.push(n)
return analytics
}
}
for (var n = 0; n < analytics.methods.length; n++) {
var key = analytics.methods[n]
analytics[key] = analytics.factory(key)
}
analytics.load = function (key, n) {
var t = document.createElement('script')
t.type = 'text/javascript'
t.async = !0
t.setAttribute('data-global-segment-analytics-key', i)
t.src =
'https://cdn.segment.com/analytics.js/v1/' +
key +
'/analytics.min.js'
var r = document.getElementsByTagName('script')[0]
r.parentNode.insertBefore(t, r)
analytics._loadOptions = n
analytics._writeKey = key
}
analytics.SNIPPET_VERSION = '5.2.0'
}
})()
</script>
</head>
<body></body>
</html>
11 changes: 11 additions & 0 deletions packages/browser/src/browser/standalone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
loadAjsClassicFallback,
isAnalyticsCSPError,
} from '../lib/csp-detection'
import { setGlobalAnalyticsKey } from '../lib/global-analytics-helper'

let ajsIdentifiedCSP = false

Expand Down Expand Up @@ -71,6 +72,16 @@ async function attempt<T>(promise: () => Promise<T>) {
}
}

const globalAnalyticsKey = (
document.querySelector(
'script[data-global-segment-analytics-key]'
) as HTMLScriptElement
)?.dataset.globalSegmentAnalyticsKey

if (globalAnalyticsKey) {
setGlobalAnalyticsKey(globalAnalyticsKey)
}

if (shouldPolyfill()) {
// load polyfills in order to get AJS to work with old browsers
const script = document.createElement('script')
Expand Down

0 comments on commit 5c1511f

Please sign in to comment.