-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make page context resilient to quick navigation changes (#852)
- Loading branch information
Showing
40 changed files
with
1,947 additions
and
1,106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@segment/analytics-core': patch | ||
--- | ||
|
||
Tighten isPlainObject type guard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@segment/analytics-next': minor | ||
--- | ||
|
||
- Capture page context information faster, so context.campaign and context.page are more resilient to quick navigation changes. | ||
- Parse UTM params into context.campaign if users pass an object to a page call. |
233 changes: 233 additions & 0 deletions
233
examples/standalone-playground/pages/index-buffered-page-ctx.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
<html> | ||
|
||
<head> | ||
<style> | ||
body { | ||
font-family: monospace; | ||
} | ||
|
||
#event { | ||
margin: 2em 0; | ||
min-height: 200px; | ||
min-width: 700px; | ||
} | ||
</style> | ||
|
||
<form method="get"> | ||
<input type="text" name="writeKey" placeholder="Writekey" /> | ||
<button>Load</button> | ||
</form> | ||
|
||
<button id="reset">Rerun Test (Reset Params + Reload)</button> | ||
|
||
<script> | ||
const { searchParams } = new URL(document.location); | ||
const writeKey = searchParams.get("writeKey"); | ||
document.querySelector("input").value = writeKey; | ||
|
||
|
||
// add random QPs for testing bug | ||
const addRandomQp = () => { | ||
const url = new URL(window.location.href); | ||
const id = Math.round(Math.random() * 10000); | ||
url.searchParams.set("id", id); | ||
url.searchParams.set("utm_source", `source-${id}`); | ||
url.searchParams.set("utm_campaign", `campaign-${id}`); | ||
window.history.replaceState(null, "", url); | ||
} | ||
|
||
// reset added QP | ||
document.getElementById('reset').addEventListener('click', () => { | ||
let url = location.origin + location.pathname | ||
const params = new URLSearchParams(location.search); | ||
const wk = params.get('writeKey') | ||
if (wk) { | ||
url += `?writeKey=${wk}` | ||
} | ||
window.history.replaceState(null, "", url); | ||
window.location.reload() | ||
}) | ||
|
||
|
||
document.addEventListener('DOMContentLoaded', () => addRandomQp()) | ||
|
||
|
||
|
||
if (writeKey) { | ||
console.profile('snippet') | ||
console.time('snippet') | ||
!(function () { | ||
|
||
var analytics = (window.analytics = window.analytics || []) | ||
if (!analytics.initialize) | ||
if (analytics.invoked) | ||
window.console && | ||
console.error && | ||
console.error('Segment snippet included twice.') | ||
else { | ||
|
||
analytics.invoked = !0 | ||
analytics.methods = [ | ||
'screen', | ||
'register', | ||
'deregister', | ||
'trackSubmit', | ||
'trackClick', | ||
'trackLink', | ||
'trackForm', | ||
'pageview', | ||
'identify', | ||
'reset', | ||
'group', | ||
'track', | ||
'ready', | ||
'alias', | ||
'debug', | ||
'page', | ||
'once', | ||
'off', | ||
'on', | ||
'addSourceMiddleware', | ||
'addIntegrationMiddleware', | ||
'setAnonymousId', | ||
'addDestinationMiddleware', | ||
] | ||
|
||
analytics.factory = function (e) { | ||
// add this function - using single key names to save bytes | ||
function p() { | ||
var c = document.querySelector("link[rel='canonical']"); | ||
return { | ||
__t: 'bpc', // discriminant key for extra uniqueness guarantee | ||
c: c && c.getAttribute('href'), | ||
p: location.pathname, | ||
u: location.href, | ||
s: location.search, | ||
t: document.title, | ||
r: document.referrer, | ||
} | ||
} | ||
return function () { | ||
var t = Array.prototype.slice.call(arguments) | ||
// add buffered page context to these calls | ||
if (['track', 'screen', 'alias', 'group', 'page', 'identify'].indexOf(e) > -1) t.push(p()); | ||
t.unshift(e) | ||
analytics.push(t) | ||
return analytics | ||
} | ||
} | ||
for (var e = 0; e < analytics.methods.length; e++) { | ||
var key = analytics.methods[e] | ||
analytics[key] = analytics.factory(key) | ||
} | ||
analytics.load = function (key, e) { | ||
var t = document.createElement('script') | ||
t.type = 'text/javascript' | ||
t.async = !0 | ||
t.src = '/node_modules/@segment/analytics-next/dist/umd/standalone.js' | ||
var n = document.getElementsByTagName('script')[0] | ||
n.parentNode.insertBefore(t, n) | ||
analytics._loadOptions = e | ||
} | ||
analytics.SNIPPET_VERSION = '4.13.1' | ||
analytics._writeKey = writeKey | ||
analytics.load() | ||
analytics.page() | ||
} | ||
})() | ||
} | ||
</script> | ||
</head> | ||
|
||
<body> | ||
<p> | ||
This is for testing that the page context is buffered when users make quick navigation changes. | ||
When this page first loads, it should immediately add some query parameters (similuating a quick navigation change). | ||
The page call should still have the correct campaign and page parameters. | ||
</p> | ||
<form> | ||
<textarea name="event" id="event"> | ||
{ | ||
"name": "hi", | ||
"properties": { }, | ||
"traits": { }, | ||
"options": { } | ||
} | ||
</textarea> | ||
<div> | ||
<button id="track">Track</button> | ||
<button id="identify">Identify</button> | ||
</div> | ||
</form> | ||
|
||
<pre id="ready-logs"></pre> | ||
<pre id="logs"></pre> | ||
|
||
<script type="text/javascript"> | ||
if (window.analytics) { | ||
// misc | ||
analytics.on('page', (...args) => console.log('analytics.on("page")', ...args)) | ||
|
||
window.analytics.ready(function onReady() { | ||
console.profileEnd('snippet') | ||
console.timeEnd('snippet') | ||
document.querySelector('#ready-logs').textContent = 'ready!' | ||
}) | ||
|
||
document.querySelector('#track').addEventListener('click', function (e) { | ||
e.preventDefault() | ||
var contents = document.querySelector('#event').value | ||
var evt = JSON.parse(contents) | ||
console.profile('track') | ||
console.time('track') | ||
var promise = window.analytics.track( | ||
evt.name || '', | ||
evt.properties || {}, | ||
evt.options || {} | ||
) | ||
|
||
promise && | ||
promise.then && | ||
promise.then(function (ctx) { | ||
console.timeEnd('track') | ||
console.profileEnd('track') | ||
ctx.flush() | ||
document.querySelector('#logs').textContent = JSON.stringify( | ||
ctx.event, | ||
null, | ||
' ' | ||
) | ||
}) | ||
}) | ||
|
||
document | ||
.querySelector('#identify') | ||
.addEventListener('click', function (e) { | ||
e.preventDefault() | ||
var contents = document.querySelector('#event').value | ||
var evt = JSON.parse(contents) | ||
console.time('identify') | ||
var promise = window.analytics.identify( | ||
evt.name || '', | ||
evt.properties || {}, | ||
evt.options || {} | ||
) | ||
|
||
promise && | ||
promise.then && | ||
promise.then(function (ctx) { | ||
console.timeEnd('identify') | ||
ctx.flush() | ||
document.querySelector('#logs').textContent = JSON.stringify( | ||
ctx.event, | ||
null, | ||
' ' | ||
) | ||
}) | ||
}) | ||
} | ||
</script> | ||
|
||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.