@mparticle/web-sdk 2.32.0 → 2.32.2
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/dist/mparticle.common.js +47 -67
- package/dist/mparticle.esm.js +47 -67
- package/dist/mparticle.js +281 -339
- package/package.json +1 -1
- package/src/audienceManager.ts +2 -2
- package/src/batchUploader.ts +2 -2
- package/src/configAPIClient.ts +4 -14
- package/src/consent.ts +4 -0
- package/src/cookieSyncManager.ts +162 -0
- package/src/identity.js +1 -5
- package/src/identityApiClient.ts +284 -0
- package/src/nativeSdkHelpers.interfaces.ts +13 -0
- package/src/persistence.interfaces.ts +3 -4
- package/src/sdkRuntimeModels.ts +7 -4
- package/src/store.ts +3 -3
- package/src/uploaders.ts +4 -4
- package/src/utils.ts +25 -0
- package/src/aliasRequestApiClient.ts +0 -89
- package/src/cookieSyncManager.js +0 -197
- package/src/identityApiClient.js +0 -131
package/package.json
CHANGED
package/src/audienceManager.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
FetchUploader,
|
|
4
4
|
XHRUploader,
|
|
5
5
|
AsyncUploader,
|
|
6
|
-
|
|
6
|
+
IFetchPayload
|
|
7
7
|
} from './uploaders';
|
|
8
8
|
import Audience from './audience';
|
|
9
9
|
|
|
@@ -38,7 +38,7 @@ export default class AudienceManager {
|
|
|
38
38
|
public async sendGetUserAudienceRequest(mpid: string, callback: (userAudiences: IAudienceMemberships) => void) {
|
|
39
39
|
this.logger.verbose('Fetching user audiences from server');
|
|
40
40
|
|
|
41
|
-
const fetchPayload:
|
|
41
|
+
const fetchPayload: IFetchPayload = {
|
|
42
42
|
method: 'GET',
|
|
43
43
|
headers: {
|
|
44
44
|
Accept: '*/*',
|
package/src/batchUploader.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
AsyncUploader,
|
|
10
10
|
FetchUploader,
|
|
11
11
|
XHRUploader,
|
|
12
|
-
|
|
12
|
+
IFetchPayload,
|
|
13
13
|
} from './uploaders';
|
|
14
14
|
import { IMParticleUser } from './identity-user-interfaces';
|
|
15
15
|
|
|
@@ -366,7 +366,7 @@ export class BatchUploader {
|
|
|
366
366
|
logger.verbose(`Batch count: ${uploads.length}`);
|
|
367
367
|
|
|
368
368
|
for (let i = 0; i < uploads.length; i++) {
|
|
369
|
-
const fetchPayload:
|
|
369
|
+
const fetchPayload: IFetchPayload = {
|
|
370
370
|
method: 'POST',
|
|
371
371
|
headers: {
|
|
372
372
|
Accept: BatchUploader.CONTENT_TYPE,
|
package/src/configAPIClient.ts
CHANGED
|
@@ -9,10 +9,11 @@ import {
|
|
|
9
9
|
import { Dictionary } from './utils';
|
|
10
10
|
import {
|
|
11
11
|
AsyncUploader,
|
|
12
|
-
|
|
12
|
+
IFetchPayload,
|
|
13
13
|
FetchUploader,
|
|
14
14
|
XHRUploader,
|
|
15
15
|
} from './uploaders';
|
|
16
|
+
import { IPixelConfiguration } from './cookieSyncManager';
|
|
16
17
|
|
|
17
18
|
export interface IKitConfigs extends IKitFilterSettings {
|
|
18
19
|
name: string;
|
|
@@ -65,17 +66,6 @@ export interface IConsentRuleValue {
|
|
|
65
66
|
hasConsented: boolean;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
export interface IPixelConfig {
|
|
69
|
-
name: string;
|
|
70
|
-
moduleId: number;
|
|
71
|
-
esId: number;
|
|
72
|
-
isDebug: boolean;
|
|
73
|
-
isProduction: boolean;
|
|
74
|
-
settings: Dictionary;
|
|
75
|
-
frequencyCap: number;
|
|
76
|
-
pixelUrl: string;
|
|
77
|
-
redirectUrl: string;
|
|
78
|
-
}
|
|
79
69
|
|
|
80
70
|
export interface IConfigResponse {
|
|
81
71
|
appName: string;
|
|
@@ -85,7 +75,7 @@ export interface IConfigResponse {
|
|
|
85
75
|
secureServiceUrl: string;
|
|
86
76
|
minWebviewBridgeVersion: number;
|
|
87
77
|
workspaceToken: string;
|
|
88
|
-
pixelConfigs:
|
|
78
|
+
pixelConfigs: IPixelConfiguration[];
|
|
89
79
|
flags: SDKEventCustomFlags;
|
|
90
80
|
}
|
|
91
81
|
|
|
@@ -135,7 +125,7 @@ export default function ConfigAPIClient(
|
|
|
135
125
|
|
|
136
126
|
this.getSDKConfiguration = async (): Promise<IConfigResponse> => {
|
|
137
127
|
let configResponse: IConfigResponse;
|
|
138
|
-
const fetchPayload:
|
|
128
|
+
const fetchPayload: IFetchPayload = {
|
|
139
129
|
method: 'get',
|
|
140
130
|
headers: {
|
|
141
131
|
Accept: 'text/plain;charset=UTF-8',
|
package/src/consent.ts
CHANGED
|
@@ -38,6 +38,10 @@ export interface SDKConsentApi {
|
|
|
38
38
|
createConsentState: (consentState?: ConsentState) => ConsentState;
|
|
39
39
|
ConsentSerialization: IConsentSerialization;
|
|
40
40
|
createPrivacyConsent: ICreatePrivacyConsentFunction;
|
|
41
|
+
isEnabledForUserConsent: (
|
|
42
|
+
consentRules: IConsentRules,
|
|
43
|
+
user: IMParticleUser
|
|
44
|
+
) => boolean;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
export interface IConsentSerialization {
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Dictionary,
|
|
3
|
+
isEmpty,
|
|
4
|
+
createCookieSyncUrl,
|
|
5
|
+
} from './utils';
|
|
6
|
+
import Constants from './constants';
|
|
7
|
+
import { MParticleWebSDK } from './sdkRuntimeModels';
|
|
8
|
+
import { MPID } from '@mparticle/web-sdk';
|
|
9
|
+
import { IConsentRules } from './consent';
|
|
10
|
+
|
|
11
|
+
const { Messages } = Constants;
|
|
12
|
+
const { InformationMessages } = Messages;
|
|
13
|
+
|
|
14
|
+
export const DAYS_IN_MILLISECONDS = 1000 * 60 * 60 * 24;
|
|
15
|
+
|
|
16
|
+
export type CookieSyncDates = Dictionary<number>;
|
|
17
|
+
|
|
18
|
+
export interface IPixelConfiguration {
|
|
19
|
+
name?: string;
|
|
20
|
+
moduleId: number;
|
|
21
|
+
esId?: number;
|
|
22
|
+
isDebug?: boolean;
|
|
23
|
+
isProduction?: boolean;
|
|
24
|
+
settings: Dictionary<string>;
|
|
25
|
+
frequencyCap: number;
|
|
26
|
+
pixelUrl: string;
|
|
27
|
+
redirectUrl: string;
|
|
28
|
+
filteringConsentRuleValues?: IConsentRules;
|
|
29
|
+
}
|
|
30
|
+
export interface ICookieSyncManager {
|
|
31
|
+
attemptCookieSync: (
|
|
32
|
+
mpid: MPID,
|
|
33
|
+
mpidIsNotInCookies?: boolean
|
|
34
|
+
) => void;
|
|
35
|
+
performCookieSync: (
|
|
36
|
+
url: string,
|
|
37
|
+
moduleId: string,
|
|
38
|
+
mpid: MPID,
|
|
39
|
+
cookieSyncDates: CookieSyncDates,
|
|
40
|
+
) => void;
|
|
41
|
+
combineUrlWithRedirect: (
|
|
42
|
+
mpid: MPID,
|
|
43
|
+
pixelUrl: string,
|
|
44
|
+
redirectUrl: string
|
|
45
|
+
) => string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default function CookieSyncManager(
|
|
49
|
+
this: ICookieSyncManager,
|
|
50
|
+
mpInstance: MParticleWebSDK
|
|
51
|
+
) {
|
|
52
|
+
const self = this;
|
|
53
|
+
|
|
54
|
+
// Public
|
|
55
|
+
this.attemptCookieSync = (
|
|
56
|
+
mpid: MPID,
|
|
57
|
+
mpidIsNotInCookies?: boolean
|
|
58
|
+
): void => {
|
|
59
|
+
const { pixelConfigurations, webviewBridgeEnabled } = mpInstance._Store;
|
|
60
|
+
|
|
61
|
+
if (!mpid || webviewBridgeEnabled) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const persistence = mpInstance._Persistence.getPersistence();
|
|
66
|
+
|
|
67
|
+
if (isEmpty(persistence)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
pixelConfigurations.forEach((pixelSettings: IPixelConfiguration) => {
|
|
72
|
+
// set requiresConsent to false to start each additional pixel configuration
|
|
73
|
+
// set to true only if filteringConsenRuleValues.values.length exists
|
|
74
|
+
let requiresConsent = false;
|
|
75
|
+
// Filtering rules as defined in UI
|
|
76
|
+
const {
|
|
77
|
+
filteringConsentRuleValues,
|
|
78
|
+
pixelUrl,
|
|
79
|
+
redirectUrl,
|
|
80
|
+
moduleId,
|
|
81
|
+
// Tells you how often we should do a cookie sync (in days)
|
|
82
|
+
frequencyCap,
|
|
83
|
+
} = pixelSettings;
|
|
84
|
+
const { values } = filteringConsentRuleValues || {};
|
|
85
|
+
|
|
86
|
+
if (isEmpty(pixelUrl)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!isEmpty(values)) {
|
|
91
|
+
requiresConsent = true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// If MPID is new to cookies, we should not try to perform the cookie sync
|
|
95
|
+
// because a cookie sync can only occur once a user either consents or doesn't.
|
|
96
|
+
// we should not check if it's enabled if the user has a blank consent
|
|
97
|
+
if (requiresConsent && mpidIsNotInCookies) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const { isEnabledForUserConsent } = mpInstance._Consent;
|
|
102
|
+
|
|
103
|
+
if (!isEnabledForUserConsent(filteringConsentRuleValues, mpInstance.Identity.getCurrentUser())) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const cookieSyncDates: CookieSyncDates = persistence[mpid]?.csd ?? {};
|
|
108
|
+
const lastSyncDateForModule: number = cookieSyncDates[moduleId] || null;
|
|
109
|
+
|
|
110
|
+
if (!isLastSyncDateExpired(frequencyCap, lastSyncDateForModule)) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Url for cookie sync pixel
|
|
115
|
+
const fullUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl)
|
|
116
|
+
|
|
117
|
+
self.performCookieSync(
|
|
118
|
+
fullUrl,
|
|
119
|
+
moduleId.toString(),
|
|
120
|
+
mpid,
|
|
121
|
+
cookieSyncDates
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Private
|
|
127
|
+
this.performCookieSync = (
|
|
128
|
+
url: string,
|
|
129
|
+
moduleId: string,
|
|
130
|
+
mpid: MPID,
|
|
131
|
+
cookieSyncDates: CookieSyncDates,
|
|
132
|
+
): void => {
|
|
133
|
+
const img = document.createElement('img');
|
|
134
|
+
|
|
135
|
+
mpInstance.Logger.verbose(InformationMessages.CookieSync);
|
|
136
|
+
img.onload = function() {
|
|
137
|
+
cookieSyncDates[moduleId] = new Date().getTime();
|
|
138
|
+
|
|
139
|
+
mpInstance._Persistence.saveUserCookieSyncDatesToPersistence(
|
|
140
|
+
mpid,
|
|
141
|
+
cookieSyncDates
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
img.src = url;
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export const isLastSyncDateExpired = (
|
|
149
|
+
frequencyCap: number,
|
|
150
|
+
lastSyncDate?: number
|
|
151
|
+
): boolean => {
|
|
152
|
+
// If there is no lastSyncDate, then there is no previous cookie sync, so we should sync the cookie
|
|
153
|
+
if (!lastSyncDate) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Otherwise, compare the last sync date to determine if it should do a cookie sync again
|
|
158
|
+
return (
|
|
159
|
+
new Date().getTime() >
|
|
160
|
+
new Date(lastSyncDate).getTime() + frequencyCap * DAYS_IN_MILLISECONDS
|
|
161
|
+
);
|
|
162
|
+
};
|
package/src/identity.js
CHANGED
|
@@ -1231,10 +1231,7 @@ export default function Identity(mpInstance) {
|
|
|
1231
1231
|
this.getUserIdentities().userIdentities,
|
|
1232
1232
|
mpInstance._APIClient.prepareForwardingStats
|
|
1233
1233
|
);
|
|
1234
|
-
mpInstance._CookieSyncManager.attemptCookieSync(
|
|
1235
|
-
null,
|
|
1236
|
-
this.getMPID()
|
|
1237
|
-
);
|
|
1234
|
+
mpInstance._CookieSyncManager.attemptCookieSync(this.getMPID());
|
|
1238
1235
|
},
|
|
1239
1236
|
isLoggedIn: function() {
|
|
1240
1237
|
return isLoggedIn;
|
|
@@ -1563,7 +1560,6 @@ export default function Identity(mpInstance) {
|
|
|
1563
1560
|
);
|
|
1564
1561
|
|
|
1565
1562
|
mpInstance._CookieSyncManager.attemptCookieSync(
|
|
1566
|
-
previousMPID,
|
|
1567
1563
|
identityApiResult.mpid,
|
|
1568
1564
|
mpidIsNotInCookies
|
|
1569
1565
|
);
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import Constants, { HTTP_ACCEPTED, HTTP_OK } from './constants';
|
|
2
|
+
import {
|
|
3
|
+
AsyncUploader,
|
|
4
|
+
FetchUploader,
|
|
5
|
+
XHRUploader,
|
|
6
|
+
IFetchPayload,
|
|
7
|
+
} from './uploaders';
|
|
8
|
+
import { CACHE_HEADER } from './identity-utils';
|
|
9
|
+
import { parseNumber } from './utils';
|
|
10
|
+
import {
|
|
11
|
+
IAliasCallback,
|
|
12
|
+
IAliasRequest,
|
|
13
|
+
IdentityAPIMethod,
|
|
14
|
+
IIdentity,
|
|
15
|
+
IIdentityAPIRequestData,
|
|
16
|
+
} from './identity.interfaces';
|
|
17
|
+
import {
|
|
18
|
+
Callback,
|
|
19
|
+
IdentityApiData,
|
|
20
|
+
MPID,
|
|
21
|
+
UserIdentities,
|
|
22
|
+
} from '@mparticle/web-sdk';
|
|
23
|
+
import {
|
|
24
|
+
IdentityCallback,
|
|
25
|
+
IdentityResultBody,
|
|
26
|
+
IIdentityResponse,
|
|
27
|
+
} from './identity-user-interfaces';
|
|
28
|
+
import { MParticleWebSDK } from './sdkRuntimeModels';
|
|
29
|
+
|
|
30
|
+
const { HTTPCodes, Messages, IdentityMethods } = Constants;
|
|
31
|
+
|
|
32
|
+
const { Modify } = IdentityMethods;
|
|
33
|
+
|
|
34
|
+
export interface IIdentityApiClient {
|
|
35
|
+
sendAliasRequest: (
|
|
36
|
+
aliasRequest: IAliasRequest,
|
|
37
|
+
aliasCallback: IAliasCallback
|
|
38
|
+
) => Promise<void>;
|
|
39
|
+
sendIdentityRequest: (
|
|
40
|
+
identityApiRequest: IIdentityAPIRequestData,
|
|
41
|
+
method: IdentityAPIMethod,
|
|
42
|
+
callback: IdentityCallback,
|
|
43
|
+
originalIdentityApiData: IdentityApiData,
|
|
44
|
+
parseIdentityResponse: IIdentity['parseIdentityResponse'],
|
|
45
|
+
mpid: MPID,
|
|
46
|
+
knownIdentities: UserIdentities
|
|
47
|
+
) => Promise<void>;
|
|
48
|
+
getUploadUrl: (method: IdentityAPIMethod, mpid: MPID) => string;
|
|
49
|
+
getIdentityResponseFromFetch: (
|
|
50
|
+
response: Response,
|
|
51
|
+
responseBody: IdentityResultBody
|
|
52
|
+
) => IIdentityResponse;
|
|
53
|
+
getIdentityResponseFromXHR: (response: XMLHttpRequest) => IIdentityResponse;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface IAliasResponseBody {
|
|
57
|
+
message?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface IdentityApiRequestPayload extends IFetchPayload {
|
|
61
|
+
headers: {
|
|
62
|
+
Accept: string;
|
|
63
|
+
'Content-Type': string;
|
|
64
|
+
'x-mp-key': string;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default function IdentityAPIClient(
|
|
69
|
+
this: IIdentityApiClient,
|
|
70
|
+
mpInstance: MParticleWebSDK
|
|
71
|
+
) {
|
|
72
|
+
this.sendAliasRequest = async function(
|
|
73
|
+
aliasRequest: IAliasRequest,
|
|
74
|
+
aliasCallback: IAliasCallback
|
|
75
|
+
) {
|
|
76
|
+
const { verbose, error } = mpInstance.Logger;
|
|
77
|
+
const { invokeAliasCallback } = mpInstance._Helpers;
|
|
78
|
+
const { aliasUrl } = mpInstance._Store.SDKConfig;
|
|
79
|
+
const { devToken: apiKey } = mpInstance._Store;
|
|
80
|
+
|
|
81
|
+
verbose(Messages.InformationMessages.SendAliasHttp);
|
|
82
|
+
|
|
83
|
+
// https://go.mparticle.com/work/SQDSDKS-6750
|
|
84
|
+
const uploadUrl = `https://${aliasUrl}${apiKey}/Alias`;
|
|
85
|
+
const uploader: AsyncUploader = window.fetch
|
|
86
|
+
? new FetchUploader(uploadUrl)
|
|
87
|
+
: new XHRUploader(uploadUrl);
|
|
88
|
+
|
|
89
|
+
// https://go.mparticle.com/work/SQDSDKS-6568
|
|
90
|
+
const uploadPayload: IFetchPayload = {
|
|
91
|
+
method: 'post',
|
|
92
|
+
headers: {
|
|
93
|
+
Accept: 'text/plain;charset=UTF-8',
|
|
94
|
+
'Content-Type': 'application/json',
|
|
95
|
+
},
|
|
96
|
+
body: JSON.stringify(aliasRequest),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const response: Response = await uploader.upload(uploadPayload);
|
|
101
|
+
|
|
102
|
+
let message: string;
|
|
103
|
+
let aliasResponseBody: IAliasResponseBody;
|
|
104
|
+
|
|
105
|
+
// FetchUploader returns the response as a JSON object that we have to await
|
|
106
|
+
if (response.json) {
|
|
107
|
+
// HTTP responses of 202, 200, and 403 do not have a response. response.json will always exist on a fetch, but can only be await-ed when the response is not empty, otherwise it will throw an error.
|
|
108
|
+
try {
|
|
109
|
+
aliasResponseBody = await response.json();
|
|
110
|
+
} catch (e) {
|
|
111
|
+
verbose('The request has no response body');
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
// https://go.mparticle.com/work/SQDSDKS-6568
|
|
115
|
+
// XHRUploader returns the response as a string that we need to parse
|
|
116
|
+
const xhrResponse = (response as unknown) as XMLHttpRequest;
|
|
117
|
+
|
|
118
|
+
aliasResponseBody = xhrResponse.responseText
|
|
119
|
+
? JSON.parse(xhrResponse.responseText)
|
|
120
|
+
: '';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let errorMessage: string;
|
|
124
|
+
|
|
125
|
+
switch (response.status) {
|
|
126
|
+
case HTTP_OK:
|
|
127
|
+
case HTTP_ACCEPTED:
|
|
128
|
+
// https://go.mparticle.com/work/SQDSDKS-6670
|
|
129
|
+
message =
|
|
130
|
+
'Successfully sent forwarding stats to mParticle Servers';
|
|
131
|
+
break;
|
|
132
|
+
default:
|
|
133
|
+
// 400 has an error message, but 403 doesn't
|
|
134
|
+
if (aliasResponseBody?.message) {
|
|
135
|
+
errorMessage = aliasResponseBody.message;
|
|
136
|
+
}
|
|
137
|
+
message =
|
|
138
|
+
'Issue with sending Alias Request to mParticle Servers, received HTTP Code of ' +
|
|
139
|
+
response.status;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
verbose(message);
|
|
143
|
+
invokeAliasCallback(aliasCallback, response.status, errorMessage);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
const err = e as Error;
|
|
146
|
+
error('Error sending alias request to mParticle servers. ' + err);
|
|
147
|
+
invokeAliasCallback(
|
|
148
|
+
aliasCallback,
|
|
149
|
+
HTTPCodes.noHttpCoverage,
|
|
150
|
+
err.message
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
this.sendIdentityRequest = async function(
|
|
156
|
+
identityApiRequest: IIdentityAPIRequestData,
|
|
157
|
+
method: IdentityAPIMethod,
|
|
158
|
+
callback: IdentityCallback,
|
|
159
|
+
originalIdentityApiData: IdentityApiData,
|
|
160
|
+
parseIdentityResponse: IIdentity['parseIdentityResponse'],
|
|
161
|
+
mpid: MPID,
|
|
162
|
+
knownIdentities: UserIdentities
|
|
163
|
+
) {
|
|
164
|
+
const { verbose, error } = mpInstance.Logger;
|
|
165
|
+
const { invokeCallback } = mpInstance._Helpers;
|
|
166
|
+
|
|
167
|
+
verbose(Messages.InformationMessages.SendIdentityBegin);
|
|
168
|
+
if (!identityApiRequest) {
|
|
169
|
+
error(Messages.ErrorMessages.APIRequestEmpty);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
verbose(Messages.InformationMessages.SendIdentityHttp);
|
|
173
|
+
|
|
174
|
+
if (mpInstance._Store.identityCallInFlight) {
|
|
175
|
+
invokeCallback(
|
|
176
|
+
callback,
|
|
177
|
+
HTTPCodes.activeIdentityRequest,
|
|
178
|
+
'There is currently an Identity request processing. Please wait for this to return before requesting again'
|
|
179
|
+
);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const previousMPID = mpid || null;
|
|
184
|
+
const uploadUrl = this.getUploadUrl(method, mpid);
|
|
185
|
+
|
|
186
|
+
const uploader: AsyncUploader = window.fetch
|
|
187
|
+
? new FetchUploader(uploadUrl)
|
|
188
|
+
: new XHRUploader(uploadUrl);
|
|
189
|
+
|
|
190
|
+
// https://go.mparticle.com/work/SQDSDKS-6568
|
|
191
|
+
const fetchPayload: IdentityApiRequestPayload = {
|
|
192
|
+
method: 'post',
|
|
193
|
+
headers: {
|
|
194
|
+
Accept: 'text/plain;charset=UTF-8',
|
|
195
|
+
'Content-Type': 'application/json',
|
|
196
|
+
'x-mp-key': mpInstance._Store.devToken,
|
|
197
|
+
},
|
|
198
|
+
body: JSON.stringify(identityApiRequest),
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
mpInstance._Store.identityCallInFlight = true;
|
|
203
|
+
const response: Response = await uploader.upload(fetchPayload);
|
|
204
|
+
|
|
205
|
+
let identityResponse: IIdentityResponse;
|
|
206
|
+
|
|
207
|
+
if (response.json) {
|
|
208
|
+
// https://go.mparticle.com/work/SQDSDKS-6568
|
|
209
|
+
// FetchUploader returns the response as a JSON object that we have to await
|
|
210
|
+
const responseBody: IdentityResultBody = await response.json();
|
|
211
|
+
|
|
212
|
+
identityResponse = this.getIdentityResponseFromFetch(
|
|
213
|
+
response,
|
|
214
|
+
responseBody
|
|
215
|
+
);
|
|
216
|
+
} else {
|
|
217
|
+
identityResponse = this.getIdentityResponseFromXHR(
|
|
218
|
+
(response as unknown) as XMLHttpRequest
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
verbose(
|
|
223
|
+
'Received Identity Response from server: ' +
|
|
224
|
+
JSON.stringify(identityResponse.responseText)
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
parseIdentityResponse(
|
|
228
|
+
identityResponse,
|
|
229
|
+
previousMPID,
|
|
230
|
+
callback,
|
|
231
|
+
originalIdentityApiData,
|
|
232
|
+
method,
|
|
233
|
+
knownIdentities,
|
|
234
|
+
false
|
|
235
|
+
);
|
|
236
|
+
} catch (err) {
|
|
237
|
+
const errorMessage = (err as Error).message || err.toString();
|
|
238
|
+
|
|
239
|
+
mpInstance._Store.identityCallInFlight = false;
|
|
240
|
+
invokeCallback(
|
|
241
|
+
callback,
|
|
242
|
+
HTTPCodes.noHttpCoverage,
|
|
243
|
+
errorMessage,
|
|
244
|
+
);
|
|
245
|
+
error('Error sending identity request to servers' + ' - ' + err);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
this.getUploadUrl = (method: IdentityAPIMethod, mpid: MPID) => {
|
|
250
|
+
const uploadServiceUrl: string = mpInstance._Helpers.createServiceUrl(
|
|
251
|
+
mpInstance._Store.SDKConfig.identityUrl
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
const uploadUrl: string =
|
|
255
|
+
method === Modify
|
|
256
|
+
? uploadServiceUrl + mpid + '/' + method
|
|
257
|
+
: uploadServiceUrl + method;
|
|
258
|
+
|
|
259
|
+
return uploadUrl;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
this.getIdentityResponseFromFetch = (
|
|
263
|
+
response: Response,
|
|
264
|
+
responseBody: IdentityResultBody
|
|
265
|
+
): IIdentityResponse => ({
|
|
266
|
+
status: response.status,
|
|
267
|
+
responseText: responseBody,
|
|
268
|
+
cacheMaxAge: parseInt(response.headers.get(CACHE_HEADER)) || 0,
|
|
269
|
+
expireTimestamp: 0,
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
this.getIdentityResponseFromXHR = (
|
|
273
|
+
response: XMLHttpRequest
|
|
274
|
+
): IIdentityResponse => ({
|
|
275
|
+
status: response.status,
|
|
276
|
+
responseText: response.responseText
|
|
277
|
+
? JSON.parse(response.responseText)
|
|
278
|
+
: {},
|
|
279
|
+
cacheMaxAge: parseNumber(
|
|
280
|
+
response.getResponseHeader(CACHE_HEADER) || ''
|
|
281
|
+
),
|
|
282
|
+
expireTimestamp: 0,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface INativeSdkHelpers {
|
|
2
|
+
initializeSessionAttributes: (apiKey: string) => void;
|
|
3
|
+
isBridgeV2Available: (bridgeName: string) => boolean;
|
|
4
|
+
isWebviewEnabled: (
|
|
5
|
+
requiredWebviewBridgeName: string,
|
|
6
|
+
minWebviewBridgeVersion: number
|
|
7
|
+
) => boolean;
|
|
8
|
+
isBridgeV1Available: () => boolean;
|
|
9
|
+
sendToNative: (path: string, value: string) => void;
|
|
10
|
+
sendViaBridgeV1: (path: string, value: string) => void;
|
|
11
|
+
sendViaIframeToIOS: (path: string, value: string) => void;
|
|
12
|
+
sendViaBridgeV2: (path: string, value: string, requiredWebviewBridgeName: boolean) => void;
|
|
13
|
+
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { Dictionary } from './utils';
|
|
15
15
|
import { IMinifiedConsentJSONObject } from './consent';
|
|
16
16
|
import { UserAttributes } from './identity-user-interfaces';
|
|
17
|
+
import { CookieSyncDates } from './cookieSyncManager';
|
|
17
18
|
|
|
18
19
|
export type UploadsTable = Dictionary<any>;
|
|
19
20
|
export interface iForwardingStatsBatches {
|
|
@@ -79,10 +80,8 @@ export interface IPersistenceMinified extends Dictionary {
|
|
|
79
80
|
// };
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
export type CookieSyncDate = Dictionary<number>;
|
|
83
|
-
|
|
84
83
|
export interface IUserPersistenceMinified extends Dictionary {
|
|
85
|
-
csd:
|
|
84
|
+
csd: CookieSyncDates; // list of timestamps for last cookie sync per module
|
|
86
85
|
con: IMinifiedConsentJSONObject; // Consent State
|
|
87
86
|
ui: UserIdentities; // User Identities
|
|
88
87
|
ua: UserAttributes; // User Attributes
|
|
@@ -121,7 +120,7 @@ export interface IPersistence {
|
|
|
121
120
|
getDomain(doc: string, locationHostname: string): string;
|
|
122
121
|
getCartProducts(mpid: MPID): Product[];
|
|
123
122
|
setCartProducts(allProducts: Product[]): void;
|
|
124
|
-
saveUserCookieSyncDatesToPersistence(mpid: MPID, csd:
|
|
123
|
+
saveUserCookieSyncDatesToPersistence(mpid: MPID, csd: CookieSyncDates): void;
|
|
125
124
|
savePersistence(persistance: IPersistenceMinified): void;
|
|
126
125
|
getPersistence(): IPersistenceMinified;
|
|
127
126
|
getFirstSeenTime(mpid: MPID): string | null;
|
package/src/sdkRuntimeModels.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { DataPlanVersion } from '@mparticle/data-planning-models';
|
|
|
3
3
|
import {
|
|
4
4
|
MPConfiguration,
|
|
5
5
|
MPID,
|
|
6
|
-
Callback,
|
|
7
6
|
IdentityApiData,
|
|
8
7
|
} from '@mparticle/web-sdk';
|
|
9
8
|
import { IStore } from './store';
|
|
@@ -31,6 +30,8 @@ import {
|
|
|
31
30
|
} from './identity-user-interfaces';
|
|
32
31
|
import { IIdentityType } from './types.interfaces';
|
|
33
32
|
import IntegrationCapture from './integrationCapture';
|
|
33
|
+
import { INativeSdkHelpers } from './nativeSdkHelpers.interfaces';
|
|
34
|
+
import { ICookieSyncManager, IPixelConfiguration } from './cookieSyncManager';
|
|
34
35
|
|
|
35
36
|
// TODO: Resolve this with version in @mparticle/web-sdk
|
|
36
37
|
export type SDKEventCustomFlags = Dictionary<any>;
|
|
@@ -158,6 +159,7 @@ export interface MParticleWebSDK {
|
|
|
158
159
|
Logger: SDKLoggerApi;
|
|
159
160
|
MPSideloadedKit: IMPSideloadedKit;
|
|
160
161
|
_APIClient: any; // TODO: Set up API Client
|
|
162
|
+
_CookieSyncManager: ICookieSyncManager;
|
|
161
163
|
_Store: IStore;
|
|
162
164
|
_Forwarders: any;
|
|
163
165
|
_Helpers: SDKHelpersApi;
|
|
@@ -167,7 +169,7 @@ export interface MParticleWebSDK {
|
|
|
167
169
|
_SessionManager: ISessionManager;
|
|
168
170
|
_Consent: SDKConsentApi;
|
|
169
171
|
Consent: SDKConsentApi;
|
|
170
|
-
_NativeSdkHelpers:
|
|
172
|
+
_NativeSdkHelpers: INativeSdkHelpers;
|
|
171
173
|
_Persistence: IPersistence;
|
|
172
174
|
_preInit: any; // TODO: Set up API
|
|
173
175
|
_instances?: Dictionary<MParticleWebSDK>;
|
|
@@ -228,6 +230,7 @@ export interface SDKInitConfig
|
|
|
228
230
|
sideloadedKits?: MPForwarder[];
|
|
229
231
|
dataPlanOptions?: KitBlockerOptions;
|
|
230
232
|
flags?: Dictionary;
|
|
233
|
+
pixelConfigs?: IPixelConfiguration[];
|
|
231
234
|
|
|
232
235
|
aliasMaxWindow?: number;
|
|
233
236
|
deviceId?: string;
|
|
@@ -283,8 +286,8 @@ export interface SDKHelpersApi {
|
|
|
283
286
|
): boolean;
|
|
284
287
|
isObject?(item: any);
|
|
285
288
|
invokeCallback?(
|
|
286
|
-
callback:
|
|
287
|
-
code:
|
|
289
|
+
callback: IdentityCallback,
|
|
290
|
+
code: number,
|
|
288
291
|
body: string,
|
|
289
292
|
mParticleUser?: IMParticleUser,
|
|
290
293
|
previousMpid?: MPID
|