@mparticle/web-sdk 2.25.3 → 2.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-sdk",
3
- "version": "2.25.3",
3
+ "version": "2.26.1",
4
4
  "description": "mParticle core SDK for web applications",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/src/apiClient.ts CHANGED
@@ -38,9 +38,10 @@ export default function APIClient(
38
38
  const self = this;
39
39
  this.queueEventForBatchUpload = function(event: SDKEvent) {
40
40
  if (!this.uploader) {
41
+ // https://go.mparticle.com/work/SQDSDKS-6317
41
42
  const millis: number = parseNumber(mpInstance._Helpers.getFeatureFlag(
42
43
  Constants.FeatureFlags.EventBatchingIntervalMillis
43
- ));
44
+ ) as string);
44
45
  this.uploader = new BatchUploader(mpInstance, millis);
45
46
  }
46
47
  this.uploader.queueEvent(event);
@@ -0,0 +1,9 @@
1
+ export default class Audience {
2
+ public audience_id: number;
3
+
4
+ constructor(
5
+ audience_id: number,
6
+ ) {
7
+ this.audience_id = audience_id;
8
+ }
9
+ }
@@ -0,0 +1,88 @@
1
+ import { SDKLoggerApi } from './sdkRuntimeModels';
2
+ import {
3
+ FetchUploader,
4
+ XHRUploader,
5
+ AsyncUploader,
6
+ fetchPayload
7
+ } from './uploaders';
8
+ import Audience from './audience';
9
+
10
+ export interface IAudienceMembershipsServerResponse {
11
+ dt: 'cam'; // current audience memberships
12
+ ct: number; // timestamp
13
+ id: string;
14
+ audience_memberships: Audience[];
15
+ }
16
+
17
+ export interface IAudienceMemberships {
18
+ currentAudienceMemberships: Audience[];
19
+ }
20
+
21
+ export default class AudienceManager {
22
+ public url: string = '';
23
+ public userAudienceAPI: AsyncUploader;
24
+ public logger: SDKLoggerApi;
25
+
26
+ constructor(
27
+ userAudienceUrl: string,
28
+ apiKey: string,
29
+ logger: SDKLoggerApi,
30
+ ) {
31
+ this.logger = logger;
32
+ this.url = `https://${userAudienceUrl}${apiKey}/audience`;
33
+ this.userAudienceAPI = window.fetch
34
+ ? new FetchUploader(this.url)
35
+ : new XHRUploader(this.url);
36
+ }
37
+
38
+ public async sendGetUserAudienceRequest(mpid: string, callback: (userAudiences: IAudienceMemberships) => void) {
39
+ this.logger.verbose('Fetching user audiences from server');
40
+
41
+ const fetchPayload: fetchPayload = {
42
+ method: 'GET',
43
+ headers: {
44
+ Accept: '*/*',
45
+ },
46
+ };
47
+ const audienceURLWithMPID = `${this.url}?mpid=${mpid}`;
48
+
49
+ try {
50
+ const userAudiencePromise: Response = await this.userAudienceAPI.upload(
51
+ fetchPayload,
52
+ audienceURLWithMPID
53
+ );
54
+
55
+ if (
56
+ userAudiencePromise.status >= 200 &&
57
+ userAudiencePromise.status < 300
58
+ ) {
59
+ this.logger.verbose(`User Audiences successfully received`);
60
+
61
+ const userAudienceMembershipsServerResponse: IAudienceMembershipsServerResponse = await userAudiencePromise.json();
62
+ const parsedUserAudienceMemberships: IAudienceMemberships = {
63
+ currentAudienceMemberships: userAudienceMembershipsServerResponse?.audience_memberships
64
+ }
65
+
66
+ try {
67
+ callback(parsedUserAudienceMemberships);
68
+ } catch(e) {
69
+ throw new Error('Error invoking callback on user audience response.');
70
+ }
71
+
72
+ } else if (userAudiencePromise.status === 401) {
73
+ throw new Error('`HTTP error status ${userAudiencePromise.status} while retrieving User Audiences - please verify your API key.`');
74
+ } else if (userAudiencePromise.status === 403) {
75
+ throw new Error('`HTTP error status ${userAudiencePromise.status} while retrieving User Audiences - please verify your workspace is enabled for audiences.`');
76
+ } else {
77
+ // In case there is an HTTP error we did not anticipate.
78
+ throw new Error(
79
+ `Uncaught HTTP Error ${userAudiencePromise.status}.`
80
+ );
81
+ }
82
+ } catch (e) {
83
+ this.logger.error(
84
+ `Error retrieving audiences. ${e}`
85
+ );
86
+ }
87
+ }
88
+ }
@@ -10,6 +10,12 @@ import { convertEvents } from './sdkToEventsApiConverter';
10
10
  import Types from './types';
11
11
  import { getRampNumber, isEmpty } from './utils';
12
12
  import { SessionStorageVault, LocalStorageVault } from './vault';
13
+ import {
14
+ AsyncUploader,
15
+ FetchUploader,
16
+ XHRUploader,
17
+ fetchPayload
18
+ } from './uploaders';
13
19
 
14
20
  /**
15
21
  * BatchUploader contains all the logic to store/retrieve events and batches
@@ -108,11 +114,12 @@ export class BatchUploader {
108
114
  _Store: { deviceId },
109
115
  } = this.mpInstance;
110
116
 
111
- const offlineStorageFeatureFlagValue = getFeatureFlag(
117
+ // https://go.mparticle.com/work/SQDSDKS-6317
118
+ const offlineStorageFeatureFlagValue: string = getFeatureFlag(
112
119
  Constants.FeatureFlags.OfflineStorage
113
- );
120
+ ) as string;
114
121
 
115
- const offlineStoragePercentage = parseInt(
122
+ const offlineStoragePercentage: number = parseInt(
116
123
  offlineStorageFeatureFlagValue,
117
124
  10
118
125
  );
@@ -422,66 +429,4 @@ export class BatchUploader {
422
429
  }
423
430
  return null;
424
431
  }
425
- }
426
-
427
- abstract class AsyncUploader {
428
- url: string;
429
- public abstract upload(fetchPayload: fetchPayload): Promise<XHRResponse>;
430
-
431
- constructor(url: string) {
432
- this.url = url;
433
- }
434
- }
435
-
436
- class FetchUploader extends AsyncUploader {
437
- public async upload(fetchPayload: fetchPayload): Promise<XHRResponse> {
438
- const response: XHRResponse = await fetch(this.url, fetchPayload);
439
- return response;
440
- }
441
- }
442
-
443
- class XHRUploader extends AsyncUploader {
444
- public async upload(fetchPayload: fetchPayload): Promise<XHRResponse> {
445
- const response: XHRResponse = await this.makeRequest(
446
- this.url,
447
- fetchPayload.body
448
- );
449
- return response;
450
- }
451
-
452
- private async makeRequest(
453
- url: string,
454
- data: string
455
- ): Promise<XMLHttpRequest> {
456
- const xhr: XMLHttpRequest = new XMLHttpRequest();
457
- return new Promise((resolve, reject) => {
458
- xhr.onreadystatechange = () => {
459
- if (xhr.readyState !== 4) return;
460
-
461
- // Process the response
462
- if (xhr.status >= 200 && xhr.status < 300) {
463
- resolve(xhr);
464
- } else {
465
- reject(xhr);
466
- }
467
- };
468
-
469
- xhr.open('post', url);
470
- xhr.send(data);
471
- });
472
- }
473
- }
474
-
475
- interface XHRResponse {
476
- status: number;
477
- statusText?: string;
478
- }
479
-
480
- interface fetchPayload {
481
- method: string;
482
- headers: {
483
- Accept: string;
484
- 'Content-Type': string;
485
- };
486
- body: string;
487
- }
432
+ }
package/src/constants.ts CHANGED
@@ -26,6 +26,8 @@ const Constants = {
26
26
  BadKey: 'Key value cannot be object or array',
27
27
  BadLogPurchase:
28
28
  'Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions',
29
+ AudienceAPINotEnabled:
30
+ 'Your workspace is not enabled to retrieve user audiences.',
29
31
  },
30
32
  InformationMessages: {
31
33
  CookieSearch: 'Searching for cookie',
@@ -135,6 +137,7 @@ const Constants = {
135
137
  configUrl: 'jssdkcdns.mparticle.com/JS/v2/',
136
138
  identityUrl: 'identity.mparticle.com/v1/',
137
139
  aliasUrl: 'jssdks.mparticle.com/v1/identity/',
140
+ userAudienceUrl: 'nativesdks.mparticle.com/v1/',
138
141
  },
139
142
  Base64CookieKeys: {
140
143
  csm: 1,
@@ -170,6 +173,7 @@ const Constants = {
170
173
  OfflineStorage: 'offlineStorage',
171
174
  DirectUrlRouting: 'directURLRouting',
172
175
  CacheIdentity: 'cacheIdentity',
176
+ AudienceAPI: 'audienceAPI',
173
177
  },
174
178
  DefaultInstance: 'default_instance',
175
179
  CCPAPurpose: 'data_sale_opt_out',
package/src/helpers.js CHANGED
@@ -441,7 +441,6 @@ export default function Helpers(mpInstance) {
441
441
  this.inArray = utils.inArray;
442
442
  this.isObject = utils.isObject;
443
443
  this.decoded = utils.decoded;
444
- this.returnConvertedBoolean = utils.returnConvertedBoolean;
445
444
  this.parseStringOrNumber = utils.parseStringOrNumber;
446
445
  this.generateHash = utils.generateHash;
447
446
  this.generateUniqueId = utils.generateUniqueId;
package/src/identity.js CHANGED
@@ -5,15 +5,17 @@ import {
5
5
  createKnownIdentities,
6
6
  tryCacheIdentity,
7
7
  } from './identity-utils';
8
+ import AudienceManager from './audienceManager';
8
9
 
9
- var Messages = Constants.Messages,
10
- HTTPCodes = Constants.HTTPCodes;
10
+ const { Messages, HTTPCodes, FeatureFlags } = Constants;
11
+ const { ErrorMessages } = Messages;
11
12
 
12
13
  const { Identify, Modify, Login, Logout } = Constants.IdentityMethods;
13
14
 
14
15
  export default function Identity(mpInstance) {
15
16
  var self = this;
16
17
  this.idCache = null;
18
+ this.audienceManager = null;
17
19
 
18
20
  this.checkIdentitySwap = function(
19
21
  previousMPID,
@@ -1265,6 +1267,34 @@ export default function Identity(mpInstance) {
1265
1267
  getFirstSeenTime: function() {
1266
1268
  return mpInstance._Persistence.getFirstSeenTime(mpid);
1267
1269
  },
1270
+ /**
1271
+ * Get user audiences
1272
+ * @method getuserAudiences
1273
+ * @param {Function} [callback] A callback function that is invoked when the user audience request completes
1274
+ */
1275
+ getUserAudiences: function(callback) {
1276
+ // user audience API is feature flagged
1277
+ if (
1278
+ !mpInstance._Helpers.getFeatureFlag(
1279
+ FeatureFlags.AudienceAPI
1280
+ )
1281
+ ) {
1282
+ mpInstance.Logger.error(
1283
+ ErrorMessages.AudienceAPINotEnabled
1284
+ );
1285
+ return;
1286
+ }
1287
+ if (self.audienceManager === null) {
1288
+ self.audienceManager = new AudienceManager(
1289
+ mpInstance._Store.SDKConfig.userAudienceUrl,
1290
+ mpInstance._Store.devToken,
1291
+ mpInstance.Logger,
1292
+ mpid
1293
+ );
1294
+ }
1295
+
1296
+ self.audienceManager.sendGetUserAudienceRequest(mpid, callback);
1297
+ },
1268
1298
  };
1269
1299
  };
1270
1300
 
@@ -5,7 +5,7 @@ import { SDKEvent, BaseEvent, MParticleWebSDK } from './sdkRuntimeModels';
5
5
  import { convertEvents } from './sdkToEventsApiConverter';
6
6
  import * as EventsApi from '@mparticle/event-models';
7
7
  import { Batch } from '@mparticle/event-models';
8
- import { IMPSideloadedKit} from './sideloadedKit';
8
+ import { IMPSideloadedKit } from './sideloadedKit';
9
9
 
10
10
  const mockFunction = function() {
11
11
  return null;
@@ -27,7 +27,6 @@ export default class _BatchValidator {
27
27
  createServiceUrl: mockFunction,
28
28
  parseNumber: mockFunction,
29
29
  isObject: mockFunction,
30
- returnConvertedBoolean: mockFunction,
31
30
  Validators: null,
32
31
  },
33
32
  _resetForTests: mockFunction,