@mhubcloud/tms_core 3.4.5 → 3.5.0-beta.0
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/.vscode/settings.json +0 -1
- package/dist/index.js +76 -60
- package/package.json +2 -2
- package/src/defaultPublisher.ts +6 -14
- package/src/publishers/facebook.ts +44 -0
- package/src/publishers/googleAds.ts +21 -9
- package/src/types/EventToLog.ts +1 -0
- package/src/types/ServiceBusMessage.ts +1 -0
- package/src/utils/utils.ts +59 -47
- package/tests/AffiliatePort.js +2 -1
- package/tests/CJ.js +2 -1
- package/tests/Facebook.js +5 -4
- package/tests/GoogleAds.js +4 -1
- package/tests/GoogleAnalytics4.js +2 -1
- package/tests/Piano.js +2 -1
- package/tests/UniversalAnalytics.js +2 -1
package/.vscode/settings.json
CHANGED
package/dist/index.js
CHANGED
|
@@ -54,10 +54,10 @@ __export(utils_exports, {
|
|
|
54
54
|
EventPublisherBase: () => EventPublisherBase,
|
|
55
55
|
encodeEmail: () => encodeEmail,
|
|
56
56
|
extractAdCode: () => extractAdCode,
|
|
57
|
+
extractPlatformCodes: () => extractPlatformCodes,
|
|
57
58
|
flatten: () => flatten,
|
|
58
59
|
formatError: () => formatError,
|
|
59
60
|
handlePlatformRequest: () => handlePlatformRequest,
|
|
60
|
-
handleResponse: () => handleResponse,
|
|
61
61
|
logEvent: () => logEvent,
|
|
62
62
|
logException: () => logException,
|
|
63
63
|
logMessage: () => logMessage,
|
|
@@ -100,17 +100,23 @@ function logMessage(level, message, properties) {
|
|
|
100
100
|
properties
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
|
-
function logEvent(publisher2, event, region, status, payload) {
|
|
103
|
+
function logEvent(publisher2, event, region, id, status, payload) {
|
|
104
|
+
const message = status >= 200 && status < 300 ? "Event dispatched to platform" : "Event dispatch failed";
|
|
104
105
|
const properties = {
|
|
105
106
|
publisher: publisher2,
|
|
106
107
|
event,
|
|
107
108
|
region,
|
|
109
|
+
id,
|
|
108
110
|
status,
|
|
109
111
|
payload
|
|
110
112
|
};
|
|
111
|
-
logMessage(1,
|
|
113
|
+
logMessage(1, message, properties);
|
|
112
114
|
}
|
|
113
115
|
function logException(exception) {
|
|
116
|
+
aiClient?.trackMetric({
|
|
117
|
+
name: `Error/${exception.name}`,
|
|
118
|
+
value: 1
|
|
119
|
+
});
|
|
114
120
|
aiClient?.trackException({ exception });
|
|
115
121
|
}
|
|
116
122
|
function removeUndefined(originalValue) {
|
|
@@ -168,6 +174,19 @@ function extractAdCode(data, adPlatform, adCode, format = null) {
|
|
|
168
174
|
}
|
|
169
175
|
return null;
|
|
170
176
|
}
|
|
177
|
+
function extractPlatformCodes(data, adPlatform) {
|
|
178
|
+
const platformCodes = data.ads.filter((x) => {
|
|
179
|
+
return x.adPlatform === adPlatform;
|
|
180
|
+
}).sort((a, b) => b.visitAt - a.visitAt)[0];
|
|
181
|
+
if (!platformCodes) {
|
|
182
|
+
return null;
|
|
183
|
+
} else {
|
|
184
|
+
return {
|
|
185
|
+
adCodes: platformCodes.adCodes,
|
|
186
|
+
visitAt: platformCodes.visitAt
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
171
190
|
function flatten(event, separator = "_") {
|
|
172
191
|
return Object.assign(
|
|
173
192
|
{},
|
|
@@ -192,27 +211,12 @@ function prepareTestRequestHeaders(headers, origUrl, origRequest, origResponse)
|
|
|
192
211
|
headers["x-mhub-orig-response-status-code"] = origResponse.status;
|
|
193
212
|
headers["x-mhub-orig-response-status-message"] = origResponse.statusText;
|
|
194
213
|
}
|
|
195
|
-
async function handleResponse(response, event) {
|
|
196
|
-
if (!response.ok) {
|
|
197
|
-
throw new Error(
|
|
198
|
-
`HTTP Error code: ${response.status}, event: ${event}, body: ${await response.text()}`
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
const body = await response.text();
|
|
202
|
-
try {
|
|
203
|
-
return JSON.parse(body);
|
|
204
|
-
} catch (ex) {
|
|
205
|
-
return body;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
214
|
async function handlePlatformRequest({
|
|
209
215
|
source,
|
|
210
216
|
baseUrl,
|
|
211
217
|
requestOptions,
|
|
212
218
|
query = "",
|
|
213
|
-
event
|
|
214
|
-
logger,
|
|
215
|
-
handlePlatformResponse = true
|
|
219
|
+
event
|
|
216
220
|
}) {
|
|
217
221
|
if (!baseUrl || baseUrl.length < 3) {
|
|
218
222
|
throw new Error("URL for request was not provided or was not valid");
|
|
@@ -224,39 +228,42 @@ async function handlePlatformRequest({
|
|
|
224
228
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
225
229
|
headers: { ...requestOptions.headers }
|
|
226
230
|
};
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
fetchRequestOptions
|
|
230
|
-
)
|
|
231
|
-
if (process.env.PUBLISHER_TESTURL) {
|
|
232
|
-
await handleTestRequest({
|
|
233
|
-
fetchRequestOptions,
|
|
234
|
-
fullUrl,
|
|
235
|
-
query,
|
|
236
|
-
rawPlatformResponse
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
if (handlePlatformResponse) {
|
|
240
|
-
const processedPlatformResponse = await handleResponse(
|
|
241
|
-
rawPlatformResponse,
|
|
242
|
-
event.event
|
|
243
|
-
);
|
|
231
|
+
let rawPlatformResponse;
|
|
232
|
+
try {
|
|
233
|
+
rawPlatformResponse = await fetch(fullUrl, fetchRequestOptions);
|
|
234
|
+
} catch (e) {
|
|
244
235
|
logEvent(
|
|
245
236
|
source,
|
|
246
237
|
event.event,
|
|
247
238
|
event.region,
|
|
248
|
-
|
|
239
|
+
event.id,
|
|
240
|
+
0,
|
|
249
241
|
requestOptions.body ? JSON.stringify(requestOptions.body) : void 0
|
|
250
242
|
);
|
|
251
|
-
|
|
252
|
-
}
|
|
243
|
+
throw e;
|
|
244
|
+
}
|
|
245
|
+
if (rawPlatformResponse) {
|
|
246
|
+
if (process.env.PUBLISHER_TESTURL) {
|
|
247
|
+
await handleTestRequest({
|
|
248
|
+
fetchRequestOptions,
|
|
249
|
+
fullUrl,
|
|
250
|
+
query,
|
|
251
|
+
rawPlatformResponse
|
|
252
|
+
});
|
|
253
|
+
}
|
|
253
254
|
logEvent(
|
|
254
255
|
source,
|
|
255
256
|
event.event,
|
|
256
257
|
event.region,
|
|
258
|
+
event.id,
|
|
257
259
|
rawPlatformResponse.status,
|
|
258
260
|
requestOptions.body ? JSON.stringify(requestOptions.body) : void 0
|
|
259
261
|
);
|
|
262
|
+
if (!rawPlatformResponse.ok) {
|
|
263
|
+
throw new Error(
|
|
264
|
+
`HTTP Error code: ${rawPlatformResponse.status}, event: ${event.event}, region: ${event.region}, body: ${await rawPlatformResponse.text()}`
|
|
265
|
+
);
|
|
266
|
+
}
|
|
260
267
|
}
|
|
261
268
|
}
|
|
262
269
|
async function handleTestRequest(params) {
|
|
@@ -433,19 +440,13 @@ async function defaultPublisher(azureFunctionContext, serviceBusMessage, source,
|
|
|
433
440
|
if (result.status === "rejected") {
|
|
434
441
|
if (result.reason instanceof Error) {
|
|
435
442
|
const formattedError = formatError(result.reason);
|
|
436
|
-
logException(
|
|
437
|
-
azureFunctionContext.log,
|
|
438
|
-
new Error(formattedError.message)
|
|
439
|
-
);
|
|
443
|
+
logException(new Error(formattedError.message));
|
|
440
444
|
throw formattedError;
|
|
441
445
|
} else {
|
|
442
446
|
const formattedError = formatError(
|
|
443
447
|
typeof result.reason === "object" ? JSON.stringify(result.reason) : result.reason
|
|
444
448
|
);
|
|
445
|
-
logException(
|
|
446
|
-
azureFunctionContext.log,
|
|
447
|
-
new Error(formattedError.message)
|
|
448
|
-
);
|
|
449
|
+
logException(new Error(formattedError.message));
|
|
449
450
|
throw formattedError;
|
|
450
451
|
}
|
|
451
452
|
}
|
|
@@ -456,7 +457,7 @@ async function processMessage(message, log2, platformPublisher, trigger) {
|
|
|
456
457
|
source: platformPublisher.source,
|
|
457
458
|
data: JSON.stringify(message)
|
|
458
459
|
};
|
|
459
|
-
const publishers = trigger(message, log2);
|
|
460
|
+
const publishers = await trigger(message, log2);
|
|
460
461
|
if (!publishers.length) {
|
|
461
462
|
logMessage(
|
|
462
463
|
1,
|
|
@@ -476,14 +477,14 @@ async function processMessage(message, log2, platformPublisher, trigger) {
|
|
|
476
477
|
platformPublisher,
|
|
477
478
|
{
|
|
478
479
|
event: message.event.code + (message.event.name ? "/" + message.event.name : ""),
|
|
479
|
-
region: message.event.region
|
|
480
|
+
region: message.event.region,
|
|
481
|
+
id: message.messageId
|
|
480
482
|
}
|
|
481
483
|
);
|
|
482
484
|
if (res) {
|
|
483
485
|
publishedAny = true;
|
|
484
486
|
} else {
|
|
485
487
|
logException(
|
|
486
|
-
log2,
|
|
487
488
|
new Error(
|
|
488
489
|
`The message has not been published. Source: ${platformPublisher.source}`
|
|
489
490
|
)
|
|
@@ -492,7 +493,6 @@ async function processMessage(message, log2, platformPublisher, trigger) {
|
|
|
492
493
|
}
|
|
493
494
|
if (!publishedAny) {
|
|
494
495
|
logException(
|
|
495
|
-
log2,
|
|
496
496
|
new Error(
|
|
497
497
|
"The message has not been published to any publisher configuration"
|
|
498
498
|
)
|
|
@@ -606,6 +606,13 @@ var facebook = {
|
|
|
606
606
|
*/
|
|
607
607
|
async publish(log2, config, data, event) {
|
|
608
608
|
if (typeof config.id === "string" && typeof config.access_token === "string") {
|
|
609
|
+
if (!(data.user_data.fbp || data.user_data.fbc || data.user_data.client_user_agent && data.user_data.client_ip_address)) {
|
|
610
|
+
logMessage(
|
|
611
|
+
1,
|
|
612
|
+
`Facebook: excluded ${event.event} due to a lack of user identifiers`
|
|
613
|
+
);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
609
616
|
const requestOptions = {
|
|
610
617
|
method: "POST",
|
|
611
618
|
body: JSON.stringify({ data: [removeUndefined(data)] }),
|
|
@@ -678,22 +685,31 @@ var googleAds = {
|
|
|
678
685
|
"The imported event could not be attributed to a click. This may be because the event did not come from a Google Ads campaign.",
|
|
679
686
|
"The imported event can't be recorded because its click occurred before this conversion's click-through window. Make sure you import the most recent data."
|
|
680
687
|
];
|
|
688
|
+
let status = 0;
|
|
689
|
+
let error;
|
|
681
690
|
if (responseJson.partialFailureError) {
|
|
691
|
+
status = 500;
|
|
682
692
|
logMessage(1, responseJson.partialFailureError.message);
|
|
683
693
|
const trimmedMessage = responseJson.partialFailureError.message.split("., at")[0] ?? "";
|
|
684
694
|
if (!knownErrors.includes(trimmedMessage)) {
|
|
685
|
-
|
|
695
|
+
error = responseJson.partialFailureError.message;
|
|
686
696
|
}
|
|
687
697
|
} else if (responseJson.error) {
|
|
688
|
-
|
|
698
|
+
status = 500;
|
|
699
|
+
error = responseJson.error.message;
|
|
689
700
|
} else {
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
701
|
+
status = 200;
|
|
702
|
+
}
|
|
703
|
+
logEvent(
|
|
704
|
+
this.source,
|
|
705
|
+
event.event,
|
|
706
|
+
event.region,
|
|
707
|
+
event.id,
|
|
708
|
+
status,
|
|
709
|
+
requestOptions.body
|
|
710
|
+
);
|
|
711
|
+
if (error) {
|
|
712
|
+
throw new Error(error);
|
|
697
713
|
}
|
|
698
714
|
},
|
|
699
715
|
async getToken(config) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mhubcloud/tms_core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0-beta.0",
|
|
4
4
|
"description": "Core function for mHub Cloud TMS publishers",
|
|
5
5
|
"homepage": "https://mhubcloud.com/",
|
|
6
6
|
"license": "Apache 2.0",
|
|
@@ -42,6 +42,6 @@
|
|
|
42
42
|
"scripts": {
|
|
43
43
|
"test": "mocha ./tests/*.js --local-settings=./local.settings.json --timeout 100000",
|
|
44
44
|
"dev": "ts-node index.ts",
|
|
45
|
-
"build": "tsup ./src/index.ts --format cjs --target
|
|
45
|
+
"build": "tsup ./src/index.ts --format cjs --target node22"
|
|
46
46
|
}
|
|
47
47
|
}
|
package/src/defaultPublisher.ts
CHANGED
|
@@ -21,7 +21,7 @@ export async function defaultPublisher(
|
|
|
21
21
|
serviceBusMessage: ServiceBusMessage,
|
|
22
22
|
source: string,
|
|
23
23
|
platformPublisher: PlatformPublisher,
|
|
24
|
-
trigger: (a: unknown) => EventPublisher[]
|
|
24
|
+
trigger: (a: unknown) => Promise<EventPublisher[]>,
|
|
25
25
|
) {
|
|
26
26
|
if (serviceBusMessage.$schema === 'mhub/pingtest') {
|
|
27
27
|
return;
|
|
@@ -41,10 +41,7 @@ export async function defaultPublisher(
|
|
|
41
41
|
if (result.status === 'rejected') {
|
|
42
42
|
if (result.reason instanceof Error) {
|
|
43
43
|
const formattedError = utils.formatError(result.reason);
|
|
44
|
-
utils.logException(
|
|
45
|
-
azureFunctionContext.log,
|
|
46
|
-
new Error(formattedError.message),
|
|
47
|
-
);
|
|
44
|
+
utils.logException(new Error(formattedError.message));
|
|
48
45
|
throw formattedError;
|
|
49
46
|
} else {
|
|
50
47
|
const formattedError = utils.formatError(
|
|
@@ -52,10 +49,7 @@ export async function defaultPublisher(
|
|
|
52
49
|
? JSON.stringify(result.reason)
|
|
53
50
|
: (result.reason as Error['message']),
|
|
54
51
|
);
|
|
55
|
-
utils.logException(
|
|
56
|
-
azureFunctionContext.log,
|
|
57
|
-
new Error(formattedError.message),
|
|
58
|
-
);
|
|
52
|
+
utils.logException(new Error(formattedError.message));
|
|
59
53
|
throw formattedError;
|
|
60
54
|
}
|
|
61
55
|
}
|
|
@@ -75,14 +69,13 @@ async function processMessage(
|
|
|
75
69
|
message: ServiceBusMessage,
|
|
76
70
|
log: Logger,
|
|
77
71
|
platformPublisher: PlatformPublisher,
|
|
78
|
-
trigger: (a: object, log: Logger) => EventPublisher[]
|
|
72
|
+
trigger: (a: object, log: Logger) => Promise<EventPublisher[]>,
|
|
79
73
|
) {
|
|
80
|
-
// TODO Je potreba otestovat, ze se to nerozbije, kdyz jsme prestali prepisovat enqueuedAt na Date.now()
|
|
81
74
|
const logProperties: Telemetry['properties'] = {
|
|
82
75
|
source: platformPublisher.source,
|
|
83
76
|
data: JSON.stringify(message),
|
|
84
77
|
};
|
|
85
|
-
const publishers = trigger(message, log);
|
|
78
|
+
const publishers = await trigger(message, log);
|
|
86
79
|
if (!publishers.length) {
|
|
87
80
|
utils.logMessage(
|
|
88
81
|
1,
|
|
@@ -106,13 +99,13 @@ async function processMessage(
|
|
|
106
99
|
message.event.code +
|
|
107
100
|
(message.event.name ? '/' + message.event.name : ''),
|
|
108
101
|
region: message.event.region,
|
|
102
|
+
id: message.messageId,
|
|
109
103
|
},
|
|
110
104
|
);
|
|
111
105
|
if (res) {
|
|
112
106
|
publishedAny = true;
|
|
113
107
|
} else {
|
|
114
108
|
utils.logException(
|
|
115
|
-
log,
|
|
116
109
|
new Error(
|
|
117
110
|
`The message has not been published. Source: ${platformPublisher.source}`,
|
|
118
111
|
),
|
|
@@ -121,7 +114,6 @@ async function processMessage(
|
|
|
121
114
|
}
|
|
122
115
|
if (!publishedAny) {
|
|
123
116
|
utils.logException(
|
|
124
|
-
log,
|
|
125
117
|
new Error(
|
|
126
118
|
'The message has not been published to any publisher configuration',
|
|
127
119
|
),
|
|
@@ -4,6 +4,36 @@ import {
|
|
|
4
4
|
PlatformRequestOptions,
|
|
5
5
|
} from '../types/PlatformPublisher';
|
|
6
6
|
|
|
7
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
8
|
+
interface FacebookData {
|
|
9
|
+
event_name: string;
|
|
10
|
+
event_time: number;
|
|
11
|
+
action_source: string;
|
|
12
|
+
event_id: string;
|
|
13
|
+
event_source_url: string;
|
|
14
|
+
opt_out: boolean;
|
|
15
|
+
user_data: {
|
|
16
|
+
client_user_agent: string;
|
|
17
|
+
fbc: string;
|
|
18
|
+
fbp: string;
|
|
19
|
+
client_ip_address: string;
|
|
20
|
+
};
|
|
21
|
+
custom_data: {
|
|
22
|
+
currency: string;
|
|
23
|
+
value: number;
|
|
24
|
+
contents: {
|
|
25
|
+
id: string;
|
|
26
|
+
quantity: number;
|
|
27
|
+
item_price: number;
|
|
28
|
+
}[];
|
|
29
|
+
content_type: string;
|
|
30
|
+
order_id: string;
|
|
31
|
+
content_category: string;
|
|
32
|
+
};
|
|
33
|
+
[x: string]: unknown;
|
|
34
|
+
}
|
|
35
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
36
|
+
|
|
7
37
|
export const facebook: PlatformPublisher = {
|
|
8
38
|
source: 'Facebook',
|
|
9
39
|
/**
|
|
@@ -18,6 +48,20 @@ export const facebook: PlatformPublisher = {
|
|
|
18
48
|
typeof config.id === 'string' &&
|
|
19
49
|
typeof config.access_token === 'string'
|
|
20
50
|
) {
|
|
51
|
+
if (
|
|
52
|
+
!(
|
|
53
|
+
(data as FacebookData).user_data.fbp ||
|
|
54
|
+
(data as FacebookData).user_data.fbc ||
|
|
55
|
+
((data as FacebookData).user_data.client_user_agent &&
|
|
56
|
+
(data as FacebookData).user_data.client_ip_address)
|
|
57
|
+
)
|
|
58
|
+
) {
|
|
59
|
+
utils.logMessage(
|
|
60
|
+
1,
|
|
61
|
+
`Facebook: excluded ${event.event} due to a lack of user identifiers`,
|
|
62
|
+
);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
21
65
|
const requestOptions: PlatformRequestOptions = {
|
|
22
66
|
method: 'POST',
|
|
23
67
|
body: JSON.stringify({ data: [utils.removeUndefined(data)] }),
|
|
@@ -115,23 +115,35 @@ export const googleAds: GoogleAdsPlatformPublisher = {
|
|
|
115
115
|
"The imported event can't be recorded because its click occurred before this conversion's click-through window. Make sure you import the most recent data.",
|
|
116
116
|
];
|
|
117
117
|
|
|
118
|
+
let status = 0;
|
|
119
|
+
let error;
|
|
120
|
+
|
|
118
121
|
if (responseJson.partialFailureError) {
|
|
122
|
+
status = 500;
|
|
119
123
|
utils.logMessage(1, responseJson.partialFailureError.message);
|
|
120
124
|
const trimmedMessage =
|
|
121
125
|
responseJson.partialFailureError.message.split('., at')[0] ?? '';
|
|
122
126
|
if (!knownErrors.includes(trimmedMessage)) {
|
|
123
|
-
|
|
127
|
+
error = responseJson.partialFailureError.message;
|
|
124
128
|
}
|
|
125
129
|
} else if (responseJson.error) {
|
|
126
|
-
|
|
130
|
+
status = 500;
|
|
131
|
+
error = responseJson.error.message;
|
|
127
132
|
} else {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
status = 200;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
utils.logEvent(
|
|
137
|
+
this.source,
|
|
138
|
+
event.event,
|
|
139
|
+
event.region,
|
|
140
|
+
event.id,
|
|
141
|
+
status,
|
|
142
|
+
requestOptions.body,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (error) {
|
|
146
|
+
throw new Error(error);
|
|
135
147
|
}
|
|
136
148
|
},
|
|
137
149
|
|
package/src/types/EventToLog.ts
CHANGED
package/src/utils/utils.ts
CHANGED
|
@@ -73,17 +73,23 @@ export function logEvent(
|
|
|
73
73
|
publisher: string,
|
|
74
74
|
event: string,
|
|
75
75
|
region: string,
|
|
76
|
+
id: string,
|
|
76
77
|
status: number,
|
|
77
78
|
payload?: string,
|
|
78
79
|
): void {
|
|
80
|
+
const message =
|
|
81
|
+
status >= 200 && status < 300
|
|
82
|
+
? 'Event dispatched to platform'
|
|
83
|
+
: 'Event dispatch failed';
|
|
79
84
|
const properties: Telemetry['properties'] = {
|
|
80
85
|
publisher,
|
|
81
86
|
event,
|
|
82
87
|
region,
|
|
88
|
+
id,
|
|
83
89
|
status,
|
|
84
90
|
payload,
|
|
85
91
|
};
|
|
86
|
-
logMessage(1,
|
|
92
|
+
logMessage(1, message, properties);
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
/**
|
|
@@ -91,6 +97,10 @@ export function logEvent(
|
|
|
91
97
|
*/
|
|
92
98
|
export function logException(exception: Error) {
|
|
93
99
|
// log.warn(exception.message);
|
|
100
|
+
aiClient?.trackMetric({
|
|
101
|
+
name: `Error/${exception.name}`,
|
|
102
|
+
value: 1,
|
|
103
|
+
});
|
|
94
104
|
aiClient?.trackException({ exception: exception });
|
|
95
105
|
}
|
|
96
106
|
|
|
@@ -207,6 +217,27 @@ export function extractAdCode(
|
|
|
207
217
|
return null;
|
|
208
218
|
}
|
|
209
219
|
|
|
220
|
+
export function extractPlatformCodes(
|
|
221
|
+
data: {
|
|
222
|
+
ads: Ad[];
|
|
223
|
+
},
|
|
224
|
+
adPlatform: string,
|
|
225
|
+
) {
|
|
226
|
+
const platformCodes = data.ads
|
|
227
|
+
.filter((x) => {
|
|
228
|
+
return x.adPlatform === adPlatform;
|
|
229
|
+
})
|
|
230
|
+
.sort((a, b) => b.visitAt - a.visitAt)[0];
|
|
231
|
+
if (!platformCodes) {
|
|
232
|
+
return null;
|
|
233
|
+
} else {
|
|
234
|
+
return {
|
|
235
|
+
adCodes: platformCodes.adCodes,
|
|
236
|
+
visitAt: platformCodes.visitAt,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
210
241
|
/**
|
|
211
242
|
* Transforms an object to be flat, for instance for GA4
|
|
212
243
|
* @param event Event that is received
|
|
@@ -263,28 +294,6 @@ export function prepareTestRequestHeaders(
|
|
|
263
294
|
headers['x-mhub-orig-response-status-message'] = origResponse.statusText;
|
|
264
295
|
}
|
|
265
296
|
|
|
266
|
-
/**
|
|
267
|
-
* Handles HTTP response from node-fetch
|
|
268
|
-
* @param response Node-fetch response object
|
|
269
|
-
* @param event Event for which the response is
|
|
270
|
-
* @returns Deserialized response JSON
|
|
271
|
-
*/
|
|
272
|
-
export async function handleResponse(response: Response, event: string) {
|
|
273
|
-
if (!response.ok) {
|
|
274
|
-
throw new Error(
|
|
275
|
-
`HTTP Error code: ${
|
|
276
|
-
response.status
|
|
277
|
-
}, event: ${event}, body: ${await response.text()}`,
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
const body = await response.text();
|
|
281
|
-
try {
|
|
282
|
-
return JSON.parse(body) as object;
|
|
283
|
-
} catch (ex) {
|
|
284
|
-
return body;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
297
|
interface HandleRequestParams {
|
|
289
298
|
source: string;
|
|
290
299
|
baseUrl: string;
|
|
@@ -307,8 +316,6 @@ export async function handlePlatformRequest({
|
|
|
307
316
|
requestOptions,
|
|
308
317
|
query = '',
|
|
309
318
|
event,
|
|
310
|
-
logger,
|
|
311
|
-
handlePlatformResponse = true,
|
|
312
319
|
}: HandleRequestParams) {
|
|
313
320
|
if (!baseUrl || baseUrl.length < 3) {
|
|
314
321
|
// ? Mohli bychom zacit delat poradnou kontrolu validity vstupnich paramteru. Idealne pres ZOD
|
|
@@ -323,43 +330,48 @@ export async function handlePlatformRequest({
|
|
|
323
330
|
headers: { ...requestOptions.headers },
|
|
324
331
|
};
|
|
325
332
|
|
|
326
|
-
|
|
327
|
-
fullUrl,
|
|
328
|
-
fetchRequestOptions,
|
|
329
|
-
);
|
|
330
|
-
|
|
331
|
-
if (process.env.PUBLISHER_TESTURL) {
|
|
332
|
-
await handleTestRequest({
|
|
333
|
-
fetchRequestOptions,
|
|
334
|
-
fullUrl,
|
|
335
|
-
query,
|
|
336
|
-
rawPlatformResponse,
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (handlePlatformResponse) {
|
|
341
|
-
const processedPlatformResponse = await handleResponse(
|
|
342
|
-
rawPlatformResponse,
|
|
343
|
-
event.event,
|
|
344
|
-
);
|
|
333
|
+
let rawPlatformResponse: Response | undefined;
|
|
345
334
|
|
|
335
|
+
try {
|
|
336
|
+
rawPlatformResponse = await fetch(fullUrl, fetchRequestOptions);
|
|
337
|
+
} catch (e: unknown) {
|
|
346
338
|
logEvent(
|
|
347
339
|
source,
|
|
348
340
|
event.event,
|
|
349
341
|
event.region,
|
|
350
|
-
|
|
342
|
+
event.id,
|
|
343
|
+
0,
|
|
351
344
|
requestOptions.body ? JSON.stringify(requestOptions.body) : undefined,
|
|
352
345
|
);
|
|
346
|
+
throw e;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (rawPlatformResponse) {
|
|
350
|
+
if (process.env.PUBLISHER_TESTURL) {
|
|
351
|
+
await handleTestRequest({
|
|
352
|
+
fetchRequestOptions,
|
|
353
|
+
fullUrl,
|
|
354
|
+
query,
|
|
355
|
+
rawPlatformResponse,
|
|
356
|
+
});
|
|
357
|
+
}
|
|
353
358
|
|
|
354
|
-
return processedPlatformResponse;
|
|
355
|
-
} else {
|
|
356
359
|
logEvent(
|
|
357
360
|
source,
|
|
358
361
|
event.event,
|
|
359
362
|
event.region,
|
|
363
|
+
event.id,
|
|
360
364
|
rawPlatformResponse.status,
|
|
361
365
|
requestOptions.body ? JSON.stringify(requestOptions.body) : undefined,
|
|
362
366
|
);
|
|
367
|
+
|
|
368
|
+
if (!rawPlatformResponse.ok) {
|
|
369
|
+
throw new Error(
|
|
370
|
+
`HTTP Error code: ${rawPlatformResponse.status}, event: ${
|
|
371
|
+
event.event
|
|
372
|
+
}, region: ${event.region}, body: ${await rawPlatformResponse.text()}`,
|
|
373
|
+
);
|
|
374
|
+
}
|
|
363
375
|
}
|
|
364
376
|
}
|
|
365
377
|
|
package/tests/AffiliatePort.js
CHANGED
package/tests/CJ.js
CHANGED
|
@@ -118,7 +118,8 @@ async function test(serviceBusMessage) {
|
|
|
118
118
|
);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
122
|
+
async function trigger(data, log) {
|
|
122
123
|
const publishers = [];
|
|
123
124
|
if (data.event.code === 'purchase') {
|
|
124
125
|
let publisher = CJPurchasePublisher;
|
package/tests/Facebook.js
CHANGED
|
@@ -42,7 +42,7 @@ describe('test Facebook publisher', function () {
|
|
|
42
42
|
quantity: 1,
|
|
43
43
|
},
|
|
44
44
|
],
|
|
45
|
-
enqueuedAt:
|
|
45
|
+
enqueuedAt: Date.now(),
|
|
46
46
|
ads: [],
|
|
47
47
|
};
|
|
48
48
|
await test(serviceBusMessage);
|
|
@@ -63,15 +63,16 @@ async function test(serviceBusMessage) {
|
|
|
63
63
|
);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
67
|
+
async function trigger(data) {
|
|
67
68
|
const publishers = [];
|
|
68
69
|
let publisher;
|
|
69
70
|
|
|
70
71
|
// Dummy config, replace with your own
|
|
71
72
|
const config = {
|
|
72
|
-
id:
|
|
73
|
+
id: process.env.Publisher_Facebook_PixelId,
|
|
73
74
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
74
|
-
access_token:
|
|
75
|
+
access_token: process.env.Publisher_Facebook_AccessToken,
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
switch (data.event?.code) {
|
package/tests/GoogleAds.js
CHANGED
|
@@ -48,6 +48,7 @@ describe('test GoogleAds publisher', function () {
|
|
|
48
48
|
adPlatform: 'googleads',
|
|
49
49
|
adCodes: {
|
|
50
50
|
gclid: 'mhubcloud',
|
|
51
|
+
gcl_src: 'aw.ds',
|
|
51
52
|
},
|
|
52
53
|
visitAt: 1727173492000,
|
|
53
54
|
},
|
|
@@ -71,7 +72,8 @@ async function test(serviceBusMessage) {
|
|
|
71
72
|
);
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
76
|
+
async function trigger(data) {
|
|
75
77
|
const publishers = [];
|
|
76
78
|
let publisher;
|
|
77
79
|
|
|
@@ -97,6 +99,7 @@ function trigger(data) {
|
|
|
97
99
|
publishers.push(publisher);
|
|
98
100
|
break;
|
|
99
101
|
}
|
|
102
|
+
|
|
100
103
|
return publishers;
|
|
101
104
|
}
|
|
102
105
|
|
|
@@ -63,7 +63,8 @@ async function test(serviceBusMessage) {
|
|
|
63
63
|
);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
67
|
+
async function trigger(data) {
|
|
67
68
|
const publishers = [];
|
|
68
69
|
const config = { trackingId: 'G-289495622' };
|
|
69
70
|
|
package/tests/Piano.js
CHANGED
|
@@ -63,7 +63,8 @@ async function test(serviceBusMessage) {
|
|
|
63
63
|
);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
67
|
+
async function trigger(data) {
|
|
67
68
|
const publishers = [];
|
|
68
69
|
const config = {
|
|
69
70
|
collectionDomain: 'xxxxx.xiti.com', // Secured collection domain
|
|
@@ -54,7 +54,8 @@ async function test(serviceBusMessage) {
|
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
58
|
+
async function trigger(data) {
|
|
58
59
|
const publishers = [];
|
|
59
60
|
const config = { trackingId: 'UA-xxxxxxx-yy' };
|
|
60
61
|
|