1
0
mirror of synced 2025-12-22 03:16:52 -05:00

Add page_event_id to all successive events (#17738)

* Add `page_event_id` to all successive events

* Update events.js

* Break out event inits into functions so they don't break each other

* Update events.js

* Update events.js

* Update events.js
This commit is contained in:
Kevin Heis
2021-02-09 07:40:27 -08:00
committed by GitHub
parent b3764cc4da
commit 207c536609
3 changed files with 44 additions and 32 deletions

View File

@@ -31,7 +31,6 @@ export function sendEvent ({
type,
version = '1.0.0',
page_render_duration,
exit_page_id,
exit_first_paint,
exit_dom_interactive,
exit_dom_complete,
@@ -60,6 +59,7 @@ export function sendEvent ({
user: getUserEventsId(),
version,
created: new Date().toISOString(),
page_event_id: pageEventId,
// Content information
path: location.pathname,
@@ -84,7 +84,6 @@ export function sendEvent ({
page_render_duration,
// Exit event
exit_page_id,
exit_first_paint,
exit_dom_interactive,
exit_dom_complete,
@@ -149,7 +148,6 @@ function trackScroll () {
function sendExit () {
if (sentExit) return
if (document.visibilityState !== 'hidden') return
if (!pageEventId) return
sentExit = true
const {
firstContentfulPaint,
@@ -158,7 +156,6 @@ function sendExit () {
} = getPerformance()
return sendEvent({
type: 'exit',
exit_page_id: pageEventId,
exit_first_paint: firstContentfulPaint,
exit_dom_interactive: domInteractive,
exit_dom_complete: domComplete,
@@ -167,22 +164,24 @@ function sendExit () {
})
}
export default function initializeEvents () {
// Page event
function initPageEvent () {
const { render } = getPerformance()
const pageEvent = sendEvent({
type: 'page',
page_render_duration: render
})
pageEventId = pageEvent?.context?.event_id
}
// Clipboard event
;['copy', 'cut', 'paste'].forEach(verb => {
function initClipboardEvent () {
['copy', 'cut', 'paste'].forEach(verb => {
document.documentElement.addEventListener(verb, () => {
sendEvent({ type: 'clipboard', clipboard_operation: verb })
})
})
}
// Link event
function initLinkEvent () {
document.documentElement.addEventListener('click', evt => {
const link = evt.target.closest('a[href^="http"]')
if (!link) return
@@ -191,10 +190,16 @@ export default function initializeEvents () {
link_url: link.href
})
})
}
function initExitEvent () {
window.addEventListener('scroll', trackScroll)
document.addEventListener('visibilitychange', sendExit)
}
function initNavigateEvent () {
if (!document.querySelector('.sidebar-products')) return
// Navigate event
Array.from(
document.querySelectorAll('.sidebar-products details')
).forEach(details => details.addEventListener(
@@ -213,9 +218,17 @@ export default function initializeEvents () {
navigate_label: `link: ${link.href}`
})
})
// Exit event
pageEventId = pageEvent?.context?.event_id
window.addEventListener('scroll', trackScroll)
document.addEventListener('visibilitychange', sendExit)
}
export default function initializeEvents () {
initPageEvent() // must come first
initExitEvent()
initLinkEvent()
initClipboardEvent()
initNavigateEvent()
// print event in ./print.js
// survey event in ./helpfulness.js
// experiment event in ./experiment.js
// search event in ./search.js
// redirect event in middleware/record-redirect.js
}

View File

@@ -32,6 +32,11 @@ const context = {
format: 'date-time',
description: 'The time we created the event; please reference UTC.'
},
page_event_id: {
type: 'string',
description: 'The id of the corresponding `page` event.',
format: 'uuid'
},
// Content information
path: {
@@ -132,8 +137,7 @@ const exitSchema = {
additionalProperties: false,
required: [
'type',
'context',
'exit_page_id'
'context'
],
properties: {
context,
@@ -141,12 +145,6 @@ const exitSchema = {
type: 'string',
pattern: '^exit$'
},
exit_page_id: {
type: 'string',
format: 'uuid',
description: 'The value of the corresponding `page` event.'
// id of the "page" event
},
exit_first_paint: {
type: 'number',
minimum: 0.001,

View File

@@ -119,6 +119,16 @@ describe('POST /events', () => {
}, 400)
)
it('should allow page_event_id', () =>
checkEvent({
...pageExample,
context: {
...pageExample.context,
page_event_id: baseExample.context.event_id
}
}, 201)
)
it('should not allow a honeypot token', () =>
checkEvent({
...pageExample,
@@ -281,7 +291,6 @@ describe('POST /events', () => {
const exitExample = {
...baseExample,
type: 'exit',
exit_page_id: 'c93c2d16-8e07-43d5-bc3c-eacc999c184d',
exit_first_paint: 0.1,
exit_dom_interactive: 0.2,
exit_dom_complete: 0.3,
@@ -293,14 +302,6 @@ describe('POST /events', () => {
checkEvent(exitExample, 201)
)
it('should require exit_page_id', () =>
checkEvent({ ...exitExample, exit_page_id: undefined }, 400)
)
it('should require exit_page_id is a uuid', () =>
checkEvent({ ...exitExample, exit_page_id: 'afjdskalj' }, 400)
)
it('exit_first_paint is a number', () =>
checkEvent({ ...exitExample, exit_first_paint: 'afjdkl' }, 400)
)