Skip to content

Commit

Permalink
Fix query string bug (#888)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Jackins <[email protected]>
  • Loading branch information
danieljackins and danieljackins authored Jul 20, 2023
1 parent 2689e7d commit f3183f2
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/neat-emus-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@segment/analytics-next': patch
---

Fix query string parsing bug that was causing events containing the 'search' property with a non string value to be dropped
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,39 @@ describe('Page Enrichment', () => {
test('special page properties in event.properties (url, referrer, etc) are copied to context.page', async () => {
const eventProps = { ...helpers.pageProps }
;(eventProps as any)['should_not_show_up'] = 'hello'
const ctx = await ajs.track('My Event', eventProps)
const ctx = await ajs.page('My Event', eventProps)
const page = ctx.event.context!.page
expect(page).toEqual(
pick(eventProps, ['url', 'path', 'referrer', 'search', 'title'])
)
})

test('event page properties should not be mutated', async () => {
test('special page properties in event.properties (url, referrer, etc) are not copied to context.page in non-page calls', async () => {
const eventProps = { ...helpers.pageProps }
;(eventProps as any)['should_not_show_up'] = 'hello'
const ctx = await ajs.track('My Event', eventProps)
const page = ctx.event.context!.page
expect(page).toMatchInlineSnapshot(`
Object {
"path": "/",
"referrer": "",
"search": "",
"title": "",
"url": "http://localhost/",
}
`)
})

test('event page properties should not be mutated', async () => {
const eventProps = { ...helpers.pageProps }
const ctx = await ajs.page('My Event', eventProps)
const page = ctx.event.context!.page
expect(page).toEqual(eventProps)
})

test('page properties should have defaults', async () => {
const eventProps = pick(helpers.pageProps, ['path', 'referrer'])
const ctx = await ajs.track('My Event', eventProps)
const ctx = await ajs.page('My Event', eventProps)
const page = ctx.event.context!.page
expect(page).toEqual({
...eventProps,
Expand All @@ -91,7 +107,7 @@ describe('Page Enrichment', () => {
eventProps.referrer = ''
eventProps.path = undefined as any
eventProps.title = null as any
const ctx = await ajs.track('My Event', eventProps)
const ctx = await ajs.page('My Event', eventProps)
const page = ctx.event.context!.page
expect(page).toEqual(
expect.objectContaining({ referrer: '', path: undefined, title: null })
Expand Down
21 changes: 13 additions & 8 deletions packages/browser/src/plugins/page-enrichment/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { pick } from '../../lib/pick'
import type { Context } from '../../core/context'
import type { Plugin } from '../../core/plugin'
import { EventProperties } from '@segment/analytics-core'

interface PageDefault {
[key: string]: unknown
Expand Down Expand Up @@ -75,23 +76,27 @@ function enrichPageContext(ctx: Context): Context {

const defaultPageContext = pageDefaults()

const pageContextFromEventProps =
event.properties && pick(event.properties, Object.keys(defaultPageContext))

event.context.page = {
...defaultPageContext,
...pageContextFromEventProps,
...event.context.page,
}
let pageContextFromEventProps: Pick<EventProperties, string> | undefined =
undefined

if (event.type === 'page') {
pageContextFromEventProps =
event.properties &&
pick(event.properties, Object.keys(defaultPageContext))

event.properties = {
...defaultPageContext,
...event.properties,
...(event.name ? { name: event.name } : {}),
}
}

event.context.page = {
...defaultPageContext,
...pageContextFromEventProps,
...event.context.page,
}

return ctx
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('before loading', () => {
describe('#normalize', () => {
let object: SegmentEvent
let defaultCtx: any
const withSearchParams = (search?: string) => {
const withSearchParams = (search?: any) => {
object.context = { page: { search } }
}

Expand Down Expand Up @@ -299,6 +299,18 @@ describe('before loading', () => {
assert(obj.context.campaign.name === 'overrideName')
})

it('should allow override of .search with object', () => {
withSearchParams({
someObject: 'foo',
})

normalize(analytics, object, options, {})
assert(object)
assert(object.context)
assert(object.context.campaign === undefined)
assert(object.context.referrer === undefined)
})

it('should add .referrer.id and .referrer.type (cookies)', () => {
withSearchParams('?utm_source=source&urid=medium')

Expand Down
3 changes: 2 additions & 1 deletion packages/browser/src/plugins/segmentio/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ export function normalize(
const ctx = json.context

// This guard against missing ctx.page should not be neccessary, since context.page is always defined
const query: string = ctx.page?.search || ''
const query: string =
typeof ctx.page?.search === 'string' ? ctx.page?.search : ''

delete json.options
json.writeKey = settings?.apiKey
Expand Down

0 comments on commit f3183f2

Please sign in to comment.