-
Notifications
You must be signed in to change notification settings - Fork 141
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
Support loading analytics into a custom global variable when using snippet version 5.2.1 or later #1032
Support loading analytics into a custom global variable when using snippet version 5.2.1 or later #1032
Changes from 3 commits
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,6 @@ | ||
--- | ||
'@segment/analytics-next': patch | ||
'@internal/browser-integration-tests': patch | ||
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. This should not really be bumped. It doesn't matter, but we should leave this off the changelog. |
||
--- | ||
|
||
Support loading analytics into a custom global variable when using snippet version 5.2.1 or later |
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() }), | ||
}) | ||
) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,94 @@ | ||||||||||||||||||||||||||||||||||
<!DOCTYPE html> | ||||||||||||||||||||||||||||||||||
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. Following the pattern of the other integration tests -- should we move this file to standalone-playground? 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. This is as per how @chrisradek advised me to setup an integration test |
||||||||||||||||||||||||||||||||||
<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' | ||||||||||||||||||||||||||||||||||
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. Is this testing against the bundle that lives in the monorepo? This is loading the cdn bundle, which doesn't have the updated code AFAIK. Kind of wondering how the tests are passing. (It's be even cleaner IMO to use the segment snippet npm package with new option). See the other browser integration test's html for example FYI of how they are symlinked to this bundle. 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. Yes, after it's been built 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. @zikaari I am still a bit confused -- to rephrase: If this is loading analytics from the CDN, wouldn't this be currently testing against the version of analytics that doesn't have the changes reflected in this PR (i.e What am I missing? I would expect that the link to look more like https://github.com/segmentio/analytics-next/blob/master/playgrounds/standalone-playground/pages/index-local.html#L79 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. This does the redirection - analytics-next/packages/browser-integration-tests/src/helpers/standalone-mock.ts Lines 18 to 33 in d4f6975
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. ohhhh... I missed that detail! That's excellent! |
||||||||||||||||||||||||||||||||||
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> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ import { | |
loadAjsClassicFallback, | ||
isAnalyticsCSPError, | ||
} from '../lib/csp-detection' | ||
import { setGlobalAnalyticsKey } from '../lib/global-analytics-helper' | ||
|
||
let ajsIdentifiedCSP = false | ||
|
||
|
@@ -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) | ||
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. This was a good idea to live here, so it doesn't get included in the npm bundle. |
||
} | ||
|
||
if (shouldPolyfill()) { | ||
// load polyfills in order to get AJS to work with old browsers | ||
const script = document.createElement('script') | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change this to minor, as this is a new feature IMO (even though it does kind of have a fix element)