2
2
import "./utils/polyfills" ;
3
3
import { uuid , getLanguage } from "./utils" ;
4
4
import UAParser from "ua-parser-js" ;
5
+ import merge from 'deepmerge' ;
5
6
6
7
// AWS SDK.
7
8
import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity-browser/CognitoIdentityClient" ;
8
9
import { GetCredentialsForIdentityCommand } from "@aws-sdk/client-cognito-identity-browser/commands/GetCredentialsForIdentityCommand" ;
9
10
import { GetIdCommand } from "@aws-sdk/client-cognito-identity-browser/commands/GetIdCommand" ;
10
11
import { PinpointClient } from "@aws-sdk/client-pinpoint-browser/PinpointClient" ;
11
12
import { PutEventsCommand } from "@aws-sdk/client-pinpoint-browser/commands/PutEventsCommand" ;
12
- import { UpdateEndpointCommand } from "@aws-sdk/client-pinpoint-browser/commands/UpdateEndpointCommand" ;
13
13
14
14
const {
15
15
_attributes,
@@ -122,6 +122,7 @@ const getMetrics = (extra = {}) =>
122
122
...carry ,
123
123
[ name ] : Number ( typeof value === 'function' ? value ( ) : value ) ,
124
124
} ) , { } ) ;
125
+ const overwriteMerge = ( destinationArray , sourceArray ) => sourceArray ;
125
126
126
127
/**
127
128
* Initialise cognito services.
@@ -220,85 +221,81 @@ const Analytics = {
220
221
return await Analytics . client ;
221
222
} ,
222
223
updateEndpoint : async ( endpoint = { } ) => {
223
- // Get client & authenticate.
224
- const client = await Analytics . getClient ( ) ;
225
- // Get endpoint ID.
226
- const UserId = Analytics . getUserId ( ) ;
227
- if ( ! UserId ) {
228
- console . error ( "No User ID found. Make sure to call Analytics.authenticate() first." ) ;
229
- return ;
230
- }
231
-
232
- const EndpointId = UserId . replace ( `${ Config . CognitoRegion } :` , "" ) ;
224
+ return await Analytics . flushEvents ( endpoint ) ;
225
+ } ,
226
+ getEndpoint : ( ) => {
227
+ try {
228
+ const ParsedEndpoint = JSON . parse ( localStorage . getItem ( `aws.pinpoint.endpoint` ) ) ;
229
+ return ParsedEndpoint || { } ;
230
+ } catch ( error ) {
231
+ return { } ;
232
+ } ;
233
+ } ,
234
+ setEndpoint : ( endpoint ) => localStorage . setItem ( `aws.pinpoint.endpoint` , JSON . stringify ( endpoint ) ) ,
235
+ mergeEndpointData : ( endpoint = { } ) => {
236
+ const Existing = Analytics . getEndpoint ( ) ;
233
237
const UAData = UAParser ( navigator . userAgent ) ;
234
238
const EndpointData = {
235
- Address : "" , // Destination for push notifications / campaigns.
236
- Attributes : {
237
- DeviceMake : [ UAData . device . vendor || "" ] ,
238
- DeviceModel : [ UAData . device . model || "" ] ,
239
- DeviceType : [ UAData . device . type || "" ]
240
- } ,
241
- ChannelType : "CUSTOM" , // GCM | APNS | APNS_SANDBOX | APNS_VOIP | APNS_VOIP_SANDBOX | ADM | SMS | VOICE | EMAIL | BAIDU | CUSTOM,
239
+ Attributes : { } ,
242
240
Demographic : {
243
241
AppVersion : Data . AppVersion || "" ,
244
242
Locale : getLanguage ( ) ,
245
- Make : UAData . engine . name || "" ,
246
- Model : UAData . browser . name || "" ,
247
- ModelVersion : UAData . browser . version || "" ,
248
- Platform : UAData . os . name || "" ,
249
- PlatformVersion : UAData . os . version || ""
250
243
} ,
251
244
Location : { } ,
252
- EffectiveDate : new Date ( ) . toISOString ( ) ,
253
245
Metrics : { } ,
254
- OptOut : "ALL" ,
255
- RequestId : uuid ( ) ,
256
- User : {
257
- UserAttributes : { } ,
258
- UserId : UserId
259
- }
260
246
} ;
261
247
262
- // Merge new endpoint data with defaults.
263
- const EndpointRequest = Object . entries ( EndpointData ) . reduce ( ( carry , [ key , value ] ) => {
264
- if ( typeof value === "object" ) {
265
- carry [ key ] = Object . assign ( value , endpoint [ key ] || { } ) ;
266
- } else {
267
- carry [ key ] = endpoint [ key ] || value ;
268
- }
269
- return carry ;
270
- } , { } ) ;
271
-
272
- const PrevEndpoint = Analytics . getEndpoint ( UserId ) ;
273
- if ( PrevEndpoint && JSON . stringify ( PrevEndpoint ) === JSON . stringify ( EndpointRequest ) ) {
274
- return EndpointRequest ;
248
+ // Add device attributes.
249
+ if ( UAData . device && UAData . device . vendor ) {
250
+ EndpointData . Attributes . DeviceMake = [ UAData . device . vendor ] ;
251
+ }
252
+ if ( UAData . device && UAData . device . model ) {
253
+ EndpointData . Attributes . DeviceModel = [ UAData . device . model ] ;
254
+ }
255
+ if ( UAData . device && UAData . device . type ) {
256
+ EndpointData . Attributes . DeviceType = [ UAData . device . type ] ;
275
257
}
276
258
277
- try {
278
- const command = new UpdateEndpointCommand ( {
279
- ApplicationId : Config . PinpointId ,
280
- EndpointId : EndpointId ,
281
- EndpointRequest : EndpointRequest
282
- } ) ;
283
- await client . send ( command ) ;
284
- Analytics . setEndpoint ( UserId , EndpointRequest ) ;
285
- return EndpointRequest ;
286
- } catch ( error ) {
287
- console . error ( error ) ;
259
+ // Add demographic data.
260
+ if ( UAData . engine && UAData . engine . name ) {
261
+ EndpointData . Demographic . Make = UAData . engine . name ;
288
262
}
263
+ if ( UAData . browser && UAData . browser . name ) {
264
+ EndpointData . Demographic . Model = UAData . browser . name ;
265
+ }
266
+ if ( UAData . browser && UAData . browser . version ) {
267
+ EndpointData . Demographic . ModelVersion = UAData . browser . version ;
268
+ }
269
+ if ( UAData . os && UAData . os . name ) {
270
+ EndpointData . Demographic . Platform = UAData . os . name ;
271
+ }
272
+ if ( UAData . os && UAData . os . version ) {
273
+ EndpointData . Demographic . PlatformVersion = UAData . os . version ;
274
+ }
275
+
276
+ // Merge new endpoint data with defaults.
277
+ endpoint = merge . all ( [ EndpointData , Existing , endpoint ] , {
278
+ arrayMerge : overwriteMerge
279
+ } ) ;
280
+
281
+ // Store the endpoint data.
282
+ Analytics . setEndpoint ( endpoint ) ;
283
+
284
+ return endpoint ;
289
285
} ,
290
- getEndpoint : id => {
291
- try {
292
- const ParsedEndpoint = JSON . parse ( localStorage . getItem ( `aws.pinpoint.endpoint.${ id } ` ) ) ;
293
- if ( ParsedEndpoint . User . UserId === id ) {
294
- return ParsedEndpoint ;
295
- }
296
- } catch ( error ) { }
297
- return false ;
298
- } ,
299
- setEndpoint : ( id , endpoint ) => localStorage . setItem ( `aws.pinpoint.endpoint.${ id } ` , JSON . stringify ( endpoint ) ) ,
300
286
events : [ ] ,
301
- record : ( type , data = { } , queue = true ) => {
287
+ record : ( type , data = { } , endpoint = { } , queue = true ) => {
288
+ // Back compat, if endpoint is a boolean it is expected to be the value for queue.
289
+ if ( typeof endpoint === 'boolean' ) {
290
+ queue = endpoint ;
291
+ endpoint = { } ;
292
+ }
293
+
294
+ // Merge endpoint data.
295
+ if ( Object . entries ( endpoint ) . length ) {
296
+ Analytics . mergeEndpointData ( endpoint ) ;
297
+ }
298
+
302
299
const EventId = uuid ( ) ;
303
300
const Event = {
304
301
[ EventId ] : {
@@ -338,12 +335,7 @@ const Analytics = {
338
335
// Flush new events after 5 seconds.
339
336
Analytics . timer = setTimeout ( Analytics . flushEvents , 5000 ) ;
340
337
} ,
341
- flushEvents : async ( ) => {
342
- // Check we have events.
343
- if ( ! Analytics . events . length ) {
344
- return ;
345
- }
346
-
338
+ flushEvents : async ( endpoint = { } ) => {
347
339
// Get the client.
348
340
const client = await Analytics . getClient ( ) ;
349
341
@@ -354,12 +346,24 @@ const Analytics = {
354
346
return ;
355
347
}
356
348
349
+ // Update endpoint data if provided.
350
+ if ( Object . entries ( endpoint ) . length ) {
351
+ Analytics . mergeEndpointData ( endpoint ) ;
352
+ }
353
+
354
+ // Build endpoint data.
355
+ const Endpoint = Analytics . getEndpoint ( ) ;
356
+ Endpoint . RequestId = uuid ( ) ;
357
+
358
+ // Reduce events to an object keyed by event ID.
357
359
const Events = Analytics . events . reduce ( ( carry , event ) => ( { ...event , ...carry } ) , { } ) ;
360
+
361
+ // Build events request object.
358
362
const BatchUserId = UserId . replace ( `${ Config . CognitoRegion } :` , "" ) ;
359
363
const EventsRequest = {
360
364
BatchItem : {
361
365
[ BatchUserId ] : {
362
- Endpoint : { } ,
366
+ Endpoint : Endpoint ,
363
367
Events : Events
364
368
}
365
369
}
@@ -382,10 +386,8 @@ const Analytics = {
382
386
}
383
387
} ;
384
388
385
- /**
386
- * Set endpoint data.
387
- */
388
- Analytics . updateEndpoint ( Data . Endpoint || { } ) ;
389
+ // Set initial endpoint data.
390
+ Analytics . mergeEndpointData ( Data . Endpoint || { } ) ;
389
391
390
392
// Track sessions.
391
393
document . addEventListener ( "visibilitychange" , ( ) => {
@@ -416,12 +418,13 @@ window.addEventListener("DOMContentLoaded", () => {
416
418
Analytics . record ( "_session.start" , {
417
419
attributes : getAttributes ( )
418
420
} ) ;
419
- // Record page view event immediately.
421
+ // Record page view event & create/update endpoint immediately.
420
422
Analytics . record (
421
423
"pageView" ,
422
424
{
423
425
attributes : getAttributes ( )
424
426
} ,
427
+ { } ,
425
428
false
426
429
) ;
427
430
} ) ;
@@ -437,11 +440,12 @@ window.addEventListener("beforeunload", async () => {
437
440
438
441
// Expose userland API.
439
442
window . Altis . Analytics . updateEndpoint = Analytics . updateEndpoint ;
440
- window . Altis . Analytics . record = ( type , data = { } ) =>
443
+ window . Altis . Analytics . record = ( type , data = { } , endpoint = { } ) =>
441
444
Analytics . record (
442
445
type ,
443
446
{
444
447
attributes : getAttributes ( data . attributes || { } ) ,
445
448
metrics : getMetrics ( data . metrics || { } )
446
- }
449
+ } ,
450
+ endpoint
447
451
) ;
0 commit comments