Skip to content

Commit 3864742

Browse files
authored
Merge pull request #1 from streamsqlio/feat/pixel-adapter
Feat/pixel adapter
2 parents db25e73 + 6732ad7 commit 3864742

File tree

6 files changed

+105
-25
lines changed

6 files changed

+105
-25
lines changed

.size-snapshot.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
{
22
"dist/streamsql.esm.js": {
3-
"bundled": 7741,
4-
"minified": 3828,
5-
"gzipped": 1575,
3+
"bundled": 8133,
4+
"minified": 3944,
5+
"gzipped": 1606,
66
"treeshaked": {
77
"rollup": {
88
"code": 75,
99
"import_statements": 0
1010
},
1111
"webpack": {
12-
"code": 4442
12+
"code": 4558
1313
}
1414
}
1515
},
1616
"dist/streamsql.cjs.js": {
17-
"bundled": 9122,
18-
"minified": 4326,
19-
"gzipped": 1641
17+
"bundled": 9592,
18+
"minified": 4470,
19+
"gzipped": 1679
2020
},
2121
"dist/streamsql.min.js": {
22-
"bundled": 10015,
23-
"minified": 4153,
24-
"gzipped": 1615
22+
"bundled": 10483,
23+
"minified": 4297,
24+
"gzipped": 1655
2525
}
2626
}

integration/fixtures/streamsql.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<script type="text/javascript" src="./streamsql.min.js"></script>
7+
<title>Test Template Functions</title>
8+
</head>
9+
<body>
10+
<h1>Alt Page</h1>
11+
<input id="input-user-id" type="text" />
12+
<button id="login-button">Login</button>
13+
<button id="logout-button">Logout</button>
14+
<div id="identify-response">
15+
<!-- Plug/unplug user id here -->
16+
</div>
17+
18+
19+
<script type="application/javascript">
20+
streamsql.init('0000-0000-0000-0000'); // create client with apiKey
21+
// These should be called on (un)identify.
22+
// Test by checking the text of user-id response
23+
streamsql.onIdentify = function(userId) {
24+
document.getElementById('identify-response').innerText = userId;
25+
}
26+
streamsql.onUnidentify = function() {
27+
document.getElementById('identify-response').innerText = '';
28+
}
29+
document.getElementById('login-button').addEventListener('click', function () {
30+
var userId = document.getElementById('input-user-id').value;
31+
streamsql.identify(userId);
32+
})
33+
document.getElementById('logout-button').addEventListener('click', function () {
34+
streamsql.unidentify() // clear the userid
35+
})
36+
</script>
37+
</body>
38+
</html>

integration/index.umd.test.js

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const home = SERVER_URL + '/index.html'
22
const alt = SERVER_URL + '/alt.html'
3+
const templatePage = SERVER_URL + '/template-fns.html'
34

45
describe('integration', () => {
56
let page
@@ -29,8 +30,8 @@ describe('integration', () => {
2930
if (postData) {
3031
postData = JSON.parse(postData)
3132
}
32-
expect(postData.streamName).toMatch('clickstream')
33-
expect(postData.eventTimestamp).toBeGreaterThan(15e9)
33+
expect(postData.stream).toMatch('clickstream')
34+
expect(postData.data.timestamp).toBeGreaterThan(15e9)
3435
}, 10000)
3536

3637
it('sends page context with url, title, and referrer', async () => {
@@ -41,7 +42,7 @@ describe('integration', () => {
4142
await page.goto(home)
4243
await page.click('button#count-button')
4344
postData = postData && JSON.parse(postData)
44-
expect(postData.context).toMatchObject({
45+
expect(postData.data.context).toMatchObject({
4546
url: await page.url(),
4647
title: await page.title(),
4748
referrer: '',
@@ -50,7 +51,7 @@ describe('integration', () => {
5051
await Promise.all([page.waitForNavigation(), page.click('a')])
5152
await page.click('button#send-button')
5253
postData = postData && JSON.parse(postData)
53-
expect(postData.context).toMatchObject({
54+
expect(postData.data.context).toMatchObject({
5455
url: await page.url(),
5556
title: await page.title(),
5657
referrer: expect.stringMatching(SERVER_URL),
@@ -107,27 +108,27 @@ describe('integration', () => {
107108
await page.type('input#user-input', userId)
108109
await page.click('button#login-button')
109110
postData = postData && JSON.parse(postData)
110-
expect(postData.user).toMatchObject({ id: userId })
111+
expect(postData.data.user).toMatchObject({ id: userId })
111112
postData = undefined // reset for next page
112113

113114
// visit the other page, should persist userId
114115
await Promise.all([page.waitForNavigation(), page.click('a')])
115116
await page.click('button#send-button')
116117
postData = postData && JSON.parse(postData)
117-
expect(postData.user).toMatchObject({ id: userId })
118+
expect(postData.data.user).toMatchObject({ id: userId })
118119
postData = undefined
119120

120121
// do logout, ensure logout sent event does NOT have user id
121122
await page.click('#logout-button')
122123
postData = postData && JSON.parse(postData)
123-
expect(postData.user).toMatchObject({ id: '' })
124+
expect(postData.data.user).toMatchObject({ id: '' })
124125
postData = undefined
125126

126127
// go back and send event from home page, should NOT have user id
127128
await page.goBack()
128129
await page.click('#count-button')
129130
postData = postData && JSON.parse(postData)
130-
expect(postData.user).toMatchObject({ id: '' })
131+
expect(postData.data.user).toMatchObject({ id: '' })
131132
}, 20000)
132133

133134
it('persists user id when coming back to site', async () => {
@@ -144,7 +145,7 @@ describe('integration', () => {
144145
await page.type('input#user-input', userId)
145146
await page.click('button#login-button')
146147
postData = postData && JSON.parse(postData)
147-
expect(postData.user).toMatchObject({ id: userId })
148+
expect(postData.data.user).toMatchObject({ id: userId })
148149
postData = undefined // reset for next page
149150

150151
// visit the other page, should persist userId
@@ -153,6 +154,21 @@ describe('integration', () => {
153154
await page.goto(alt)
154155
await page.click('button#send-button')
155156
postData = postData && JSON.parse(postData)
156-
expect(postData.user).toMatchObject({ id: userId })
157+
expect(postData.data.user).toMatchObject({ id: userId })
157158
}, 8000)
159+
160+
it('calls template functions onIdentify and onUnidentify', async () => {
161+
const userId = 'user-id'
162+
const responseDivSelector = 'div#identify-response'
163+
// simulate a login that should store id to send w request
164+
await page.goto(templatePage)
165+
await page.type('#input-user-id', userId)
166+
await page.click('button#login-button')
167+
const identifyResponse = await page.$(responseDivSelector)
168+
expect(await identifyResponse.evaluate(node => node.innerText)).toBe(userId);
169+
170+
await page.click('button#logout-button')
171+
const unidentifyResponse = await page.$(responseDivSelector)
172+
expect(await unidentifyResponse.evaluate(node => node.innerText)).toBe('');
173+
})
158174
})

src/StreamSQL.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,14 @@ export default class StreamSQLClient implements CoreAPI {
3636
public identify(userId: string): StreamSQLClient {
3737
if (!this.identifier) this.throwNoInitError()
3838
this.identifier.setUser(userId)
39+
this.onIdentify(userId) // call template listener
3940
return this
4041
}
4142

4243
public unidentify(): StreamSQLClient {
4344
if (!this.identifier) this.throwNoInitError()
4445
this.identifier.deleteUser()
46+
this.onUnidentify() // call template listener
4547
return this
4648
}
4749

@@ -57,9 +59,8 @@ export default class StreamSQLClient implements CoreAPI {
5759
if (!this.pageCtx || !this.identifier) {
5860
this.throwNoInitError()
5961
}
60-
return {
61-
streamName: streamName.toLowerCase(),
62-
eventTimestamp: new Date().getTime(),
62+
const streamsqlData = {
63+
timestamp: new Date().getTime(),
6364
context: {
6465
url: this.pageCtx.location(),
6566
referrer: this.pageCtx.referrer(),
@@ -69,11 +70,20 @@ export default class StreamSQLClient implements CoreAPI {
6970
id: this.identifier.getUser(),
7071
// FUTURE: ability to add other user props
7172
},
72-
data: data || {}
73+
}
74+
const _data = data ? Object.assign({}, streamsqlData, data) : streamsqlData
75+
return {
76+
stream: streamName.toLowerCase(),
77+
data: _data
7378
}
7479
}
7580

7681
private throwNoInitError(): never {
7782
throw streamsqlErr(`api key must be set first: streamsql.init(apiKey)`)
7883
}
84+
85+
// Template functions. Originally built to allow pixel to listen for events.
86+
// @ts-ignore
87+
public onIdentify(userId: string) {}
88+
public onUnidentify() {}
7989
}

src/test/streamsql.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,20 @@ describe('StreamSQL Core', () => {
132132
})
133133
expect(() => streamsql.sendEvent('mystream')).not.toThrow()
134134
})
135+
136+
it('calls template listeners for identify, unidentify', () => {
137+
streamsql.init(apiKey)
138+
const onIdentify = jest.fn((userId: string) => userId)
139+
const onUnidentify = jest.fn()
140+
141+
streamsql.onIdentify = onIdentify
142+
streamsql.onUnidentify = onUnidentify
143+
144+
streamsql.identify('user-id')
145+
expect(onIdentify).toHaveBeenCalledTimes(1)
146+
expect(onIdentify).toHaveBeenCalledWith('user-id')
147+
148+
streamsql.unidentify()
149+
expect(onUnidentify).toHaveBeenCalledTimes(1)
150+
})
135151
})

0 commit comments

Comments
 (0)