@mhubcloud/tms_core 1.7.6 → 2.0.0-beta.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/.eslintignore +3 -0
- package/.eslintrc.cjs +87 -0
- package/.prettierignore +3 -0
- package/.prettierrc +10 -0
- package/.vscode/extensions.json +12 -0
- package/.vscode/settings.json +52 -0
- package/dist/index.js +609 -0
- package/index.js +1 -0
- package/{lib → js/lib}/defaultPublisher.js +26 -24
- package/js/lib/utils.js +349 -0
- package/js/publishers/AffiliatePort.js +78 -0
- package/{publishers → js/publishers}/CJ.js +7 -5
- package/{publishers → js/publishers}/Facebook.js +6 -4
- package/{publishers → js/publishers}/GoogleAnalytics4.js +8 -6
- package/js/publishers/HttpPublisher.js +64 -0
- package/{publishers → js/publishers}/Piano.js +6 -4
- package/{publishers → js/publishers}/UniversalAnalytics.js +7 -5
- package/package.json +46 -29
- package/releasePlan.md +3 -0
- package/src/defaultPublisher.ts +132 -0
- package/src/index.ts +25 -0
- package/src/publishers/affiliatePort.ts +69 -0
- package/src/publishers/cj.ts +67 -0
- package/src/publishers/facebook.ts +49 -0
- package/src/publishers/googleAnalytics4.ts +60 -0
- package/src/publishers/piano.ts +71 -0
- package/src/publishers/universalAnalytics.ts +63 -0
- package/src/types/EventHubMessage.ts +8 -0
- package/src/types/EventPublisher.ts +9 -0
- package/src/types/PlatformPublisher.ts +19 -0
- package/src/types/UtilTypes.ts +1 -0
- package/src/types/global.d.ts +3 -0
- package/src/utils/utils.ts +358 -0
- package/tests/AffiliatePort.js +107 -85
- package/tests/CJ.js +144 -119
- package/tests/Facebook.js +124 -103
- package/tests/GoogleAnalytics4.js +82 -74
- package/tests/Piano.js +112 -99
- package/tests/UniversalAnalytics.js +90 -77
- package/tests/testUtils.js +7 -0
- package/tsconfig.eslint.json +43 -0
- package/tsconfig.json +26 -0
- package/lib/utils.js +0 -307
- package/publishers/AffiliatePort.js +0 -61
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const fetch = require('node-fetch');
|
|
2
|
+
const utils = require("../lib/utils");
|
|
3
|
+
const SOURCE = "f_HttpPublisher";
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
/**
|
|
7
|
+
* Processed data comming from EventHub to data for further processing
|
|
8
|
+
* @param {Object} data The data comming from EventHub
|
|
9
|
+
* @param {FunctionContext} test Azure Function context.test
|
|
10
|
+
* @returns {Object} Data for further processing
|
|
11
|
+
*/
|
|
12
|
+
parse: function parse(data, test) {
|
|
13
|
+
//ConsumerBase.cs:ConsumeOneEventAsync
|
|
14
|
+
data.enqueuedAt = test ? 1600000000000 : Date.now();
|
|
15
|
+
return data;
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Publishes data to provided URL
|
|
20
|
+
* @param {FunctionContext} log Azure Function context.log.warn
|
|
21
|
+
* @param {string} event Required: event for which is it triggered
|
|
22
|
+
* @param {string} url Required: Request URL with query parameters
|
|
23
|
+
* @param {string} platform Required: Name of the plaform to which request is sent
|
|
24
|
+
* @param {string} method Required: Request method - GET|POST|PUT...
|
|
25
|
+
* @param {Object} headers Optional: Object of request headers
|
|
26
|
+
* @param {Object} body Optional: Non-strigifed request body object
|
|
27
|
+
*
|
|
28
|
+
*/
|
|
29
|
+
publish: async function publish(log, event, platform, url, method, headers = {}, body = {}) {
|
|
30
|
+
const reqOpts = {
|
|
31
|
+
method: method,
|
|
32
|
+
headers: headers
|
|
33
|
+
};
|
|
34
|
+
if(method == "POST"){
|
|
35
|
+
reqOpts.body = JSON.stringify(body);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const resp = await fetch(url, reqOpts);
|
|
39
|
+
|
|
40
|
+
if (process.env.PUBLISHER_TESTURL) {
|
|
41
|
+
try {
|
|
42
|
+
utils.prepareTestRequestHeaders(reqOpts.headers, url, reqOpts, resp);
|
|
43
|
+
await fetch(process.env.PUBLISHER_TESTURL, reqOpts);
|
|
44
|
+
} catch { }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await utils.handleResponse(resp, event);
|
|
48
|
+
|
|
49
|
+
log(`${platform} - ${event} - sent`);
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Validates an object against given schema
|
|
54
|
+
* @param {Object} data An object to validate.
|
|
55
|
+
* @param {string} schema Name of the schema. That's name of a file with `.schema.json` extension in `customizable/schemas` subfolder of current publisher folder
|
|
56
|
+
* @returns {boolean} Validation result, true if successful, false if unsuccessfull (in which case more info is written to console)
|
|
57
|
+
*/
|
|
58
|
+
validate: function validate(data, schema) {
|
|
59
|
+
if (!schema) throw new Error("Schema parameters not provided");
|
|
60
|
+
if (schema.indexOf("/") >= 0) throw new Error("Schema must be provided as schema name, not schema path");
|
|
61
|
+
//More validation done by utils.validate
|
|
62
|
+
return utils.validate(data, SOURCE, schema);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
@@ -6,22 +6,24 @@ module.exports = {
|
|
|
6
6
|
/**
|
|
7
7
|
* Processed data comming from EventHub to data for further processing
|
|
8
8
|
* @param {Object} data The data comming from EventHub
|
|
9
|
+
* @param {FunctionContext} test Azure Function context.test
|
|
9
10
|
* @returns {Object} Data for further processing
|
|
10
11
|
*/
|
|
11
|
-
parse: function parse(data,
|
|
12
|
+
parse: function parse(data, test) {
|
|
12
13
|
//ConsumerBase.cs:ConsumeOneEventAsync
|
|
13
|
-
data.enqueuedAt =
|
|
14
|
+
data.enqueuedAt = test ? 1600000000000 : Date.now();
|
|
14
15
|
return data;
|
|
15
16
|
},
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Publishes data to Piano
|
|
20
|
+
* @param {FunctionContext} log Azure Function context.log.warn
|
|
19
21
|
* @param {{collectionDomain: string, siteId: string|number}} config Publisher configuration
|
|
20
22
|
* @param {{pianoData: {events: {name: string, data: {[key: string]: any}}[]}, aux: {visitorId: string, ref: string, userAgent?: string, referer?: string, forwardedFor?: string}}} data Data in publisher-friendly format to be published
|
|
21
23
|
* @returns {*} Data returned by platform, if possible JSON-deserialized (otherwise as string)
|
|
22
24
|
* @param {string} event for which is it triggered
|
|
23
25
|
*/
|
|
24
|
-
publish: async function publish(config, data, event) {
|
|
26
|
+
publish: async function publish(log, config, data, event) {
|
|
25
27
|
data = utils.removeUndefined(data);
|
|
26
28
|
let dt = "";
|
|
27
29
|
//https://developers.atinternet-solutions.com/piano-analytics-tagging-en/event-tagging-piano-analytics-en/events-pattern-en/#post-request_5
|
|
@@ -48,7 +50,7 @@ module.exports = {
|
|
|
48
50
|
|
|
49
51
|
await utils.handleResponse(resp, event);
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
log(`Piano Analytics - ${event} - sent`);
|
|
52
54
|
},
|
|
53
55
|
|
|
54
56
|
/**
|
|
@@ -8,20 +8,22 @@ module.exports = {
|
|
|
8
8
|
/**
|
|
9
9
|
* Processed data comming from EventHub to data for further processing
|
|
10
10
|
* @param {Object} data The data comming from EventHub
|
|
11
|
-
* @
|
|
11
|
+
* @param {FunctionContext} test Azure Function context.test
|
|
12
|
+
* @returns {Object} Data for further processing
|
|
12
13
|
*/
|
|
13
|
-
parse: function parse(data,
|
|
14
|
+
parse: function parse(data, test) {
|
|
14
15
|
//ConsumerBase.cs:ConsumeOneEventAsync
|
|
15
|
-
data.enqueuedAt =
|
|
16
|
+
data.enqueuedAt = test ? 1600000000000 : Date.now();
|
|
16
17
|
return data;
|
|
17
18
|
},
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Publishes data to Google Analytics
|
|
22
|
+
* @param {FunctionContext} log Azure Function context.log.warn
|
|
21
23
|
* @param {{tid: string}} config Publisher configuration
|
|
22
24
|
* @param {{action: string, ti: string, [key:string]: string|number|boolean}} data Data in publisher-friendly format to be published
|
|
23
25
|
*/
|
|
24
|
-
publish: async function publish(config, data, event) {
|
|
26
|
+
publish: async function publish(log, config, data, event) {
|
|
25
27
|
data = utils.removeUndefined(data);
|
|
26
28
|
//https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide#event
|
|
27
29
|
const url = "https://www.google-analytics.com/collect";
|
|
@@ -55,7 +57,7 @@ module.exports = {
|
|
|
55
57
|
|
|
56
58
|
await utils.handleResponse(resp);
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
log(`Universal Analytics - ${event} - sent`);
|
|
59
61
|
},
|
|
60
62
|
|
|
61
63
|
/**
|
package/package.json
CHANGED
|
@@ -1,29 +1,46 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@mhubcloud/tms_core",
|
|
3
|
+
"version": "2.0.0-beta.1",
|
|
4
|
+
"description": "Core function for mHub Cloud TMS publishers",
|
|
5
|
+
"homepage": "https://mhubcloud.com/",
|
|
6
|
+
"license": "Apache 2.0",
|
|
7
|
+
"email": "info@crossmasters.com",
|
|
8
|
+
"author": "Jan Brzobohatý",
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"mHub Cloud",
|
|
12
|
+
"TMS",
|
|
13
|
+
"tag management system",
|
|
14
|
+
"backend measurement",
|
|
15
|
+
"server side measurement",
|
|
16
|
+
"conversion API"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"ajv": "^8.12.0",
|
|
20
|
+
"applicationinsights": "^2.6.0",
|
|
21
|
+
"node-fetch": "^2.6.11"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@azure/functions": "^3.5.1",
|
|
25
|
+
"@tsconfig/recommended": "^1.0.2",
|
|
26
|
+
"@types/node": "^18.16.14",
|
|
27
|
+
"@types/node-fetch": "^2.6.4",
|
|
28
|
+
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
|
29
|
+
"@typescript-eslint/parser": "^5.59.7",
|
|
30
|
+
"eslint": "^8.41.0",
|
|
31
|
+
"eslint-config-prettier": "^8.8.0",
|
|
32
|
+
"eslint-import-resolver-typescript": "^3.5.5",
|
|
33
|
+
"eslint-plugin-import": "^2.27.5",
|
|
34
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
35
|
+
"mocha": "^10.2.0",
|
|
36
|
+
"prettier": "^2.8.8",
|
|
37
|
+
"ts-node": "^10.9.1",
|
|
38
|
+
"tsup": "^6.7.0",
|
|
39
|
+
"typescript": "^4.9.5"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"dev": "ts-node index.ts",
|
|
43
|
+
"build": "tsup ./src/index.ts --format cjs --target node18",
|
|
44
|
+
"test": "mocha ./tests/*.js --timeout 10000 "
|
|
45
|
+
}
|
|
46
|
+
}
|
package/releasePlan.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Context, Logger } from '@azure/functions';
|
|
2
|
+
import { Telemetry } from 'applicationinsights/out/Declarations/Contracts';
|
|
3
|
+
import { EventHubMessage } from './types/EventHubMessage';
|
|
4
|
+
import { EventPublisher } from './types/EventPublisher';
|
|
5
|
+
import { PlatformPublisher } from './types/PlatformPublisher';
|
|
6
|
+
import { TypeSafeObject } from './types/UtilTypes';
|
|
7
|
+
import * as utils from './utils/utils';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Implements the Azure Function, called for set of events received via Event Hub
|
|
11
|
+
* @deprecated Udelat novou metodu, ktera bude spravne a bude inicializovat classu
|
|
12
|
+
* @param azureFunctionContext Azure Function Context
|
|
13
|
+
* @param eventHubMessages Array of messages received from Event Hub
|
|
14
|
+
* @param source Name of the publisher (it's folder name in which it's implemented)
|
|
15
|
+
* @param platformPublisher Publisher implementation instance (from <publisher>/publisher.js)
|
|
16
|
+
* @param trigger
|
|
17
|
+
*/
|
|
18
|
+
export async function defaultPublisher(
|
|
19
|
+
azureFunctionContext: Context,
|
|
20
|
+
eventHubMessages: EventHubMessage[],
|
|
21
|
+
source: string,
|
|
22
|
+
platformPublisher: PlatformPublisher,
|
|
23
|
+
trigger: (a: unknown) => EventPublisher[],
|
|
24
|
+
) {
|
|
25
|
+
const processMessagePromises = [];
|
|
26
|
+
for (const message of eventHubMessages) {
|
|
27
|
+
processMessagePromises.push(
|
|
28
|
+
processMessage(
|
|
29
|
+
message,
|
|
30
|
+
azureFunctionContext.log,
|
|
31
|
+
platformPublisher,
|
|
32
|
+
trigger,
|
|
33
|
+
),
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const results = await Promise.allSettled(processMessagePromises);
|
|
37
|
+
// ? musi nahoru probublat, ze aspon neco selhalo a to je to, co bude triggerovat nasledujici error. Error pro konkretniho publishera musi byt primo v processMessage v loopu. Hodnotu pro typ publishera vezmeme z platformBublisher.SOURCE
|
|
38
|
+
for (const result of results) {
|
|
39
|
+
if (result.status === 'rejected') {
|
|
40
|
+
utils.logException(
|
|
41
|
+
azureFunctionContext.log,
|
|
42
|
+
new Error(result.reason as Error['message']),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Processes single message from EventHub
|
|
50
|
+
* @param message A message received from EventHub
|
|
51
|
+
* @param log Azure Function context.log
|
|
52
|
+
* @param source Name of the publisher (it's folder name in which it's implemented)
|
|
53
|
+
* @param platfromPublisher Publisher implementation instance (from <publisher>/publisher.js)
|
|
54
|
+
* @param trigger Publisher-specific trigger function (from <publisher>/customizable/trigger.js)
|
|
55
|
+
* @returns Returns false if at least one publisher failed or in case of other failed requirements
|
|
56
|
+
*/
|
|
57
|
+
async function processMessage(
|
|
58
|
+
message: EventHubMessage,
|
|
59
|
+
log: Logger,
|
|
60
|
+
platfromPublisher: PlatformPublisher,
|
|
61
|
+
trigger: (a: object) => EventPublisher[],
|
|
62
|
+
) {
|
|
63
|
+
// TODO Je potreba otestovat, ze se to nerozbije, kdyz jsme prestali prepisovat enqueuedAt na Date.now()
|
|
64
|
+
const logProperties: Telemetry['properties'] = {
|
|
65
|
+
source: platfromPublisher.source,
|
|
66
|
+
data: JSON.stringify(message),
|
|
67
|
+
};
|
|
68
|
+
const publishers = trigger(message);
|
|
69
|
+
if (!publishers.length) {
|
|
70
|
+
utils.log(
|
|
71
|
+
log,
|
|
72
|
+
1,
|
|
73
|
+
'Message excluded by filter (no publishers determined)',
|
|
74
|
+
logProperties,
|
|
75
|
+
);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
let publishedAny = false;
|
|
79
|
+
let failedToPublishAll = false;
|
|
80
|
+
for (const eventPublisher of publishers) {
|
|
81
|
+
const mapped = await eventPublisher.map(message);
|
|
82
|
+
|
|
83
|
+
const res = await publishMessage(
|
|
84
|
+
log,
|
|
85
|
+
mapped,
|
|
86
|
+
eventPublisher.config,
|
|
87
|
+
platfromPublisher,
|
|
88
|
+
message.event.code + (message.event.name ? '/' + message.event.name : ''),
|
|
89
|
+
);
|
|
90
|
+
if (res) {
|
|
91
|
+
publishedAny = true;
|
|
92
|
+
} else {
|
|
93
|
+
utils.logException(
|
|
94
|
+
log,
|
|
95
|
+
new Error(
|
|
96
|
+
`The message has not been published. Source: ${platfromPublisher.source}`,
|
|
97
|
+
),
|
|
98
|
+
);
|
|
99
|
+
failedToPublishAll = true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (!publishedAny) {
|
|
103
|
+
utils.logException(
|
|
104
|
+
log,
|
|
105
|
+
new Error(
|
|
106
|
+
'The message has not been published to any publisher configuration',
|
|
107
|
+
),
|
|
108
|
+
);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
// Returns false
|
|
112
|
+
return !failedToPublishAll;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Publishes a message to configured publisher
|
|
117
|
+
* @param log Azure Function context.log
|
|
118
|
+
* @param mapped Mapped message data
|
|
119
|
+
* @param config Platform-specific platform publisher configuration
|
|
120
|
+
* @param platformPublisher Publisher implementation instance (from <publisher>/publisher.js)
|
|
121
|
+
* @param event Event for which logic was triggered
|
|
122
|
+
*/
|
|
123
|
+
async function publishMessage(
|
|
124
|
+
log: Logger,
|
|
125
|
+
mapped: TypeSafeObject,
|
|
126
|
+
config: TypeSafeObject,
|
|
127
|
+
platformPublisher: PlatformPublisher,
|
|
128
|
+
event: string,
|
|
129
|
+
) {
|
|
130
|
+
await platformPublisher.publish(log, config, mapped, event);
|
|
131
|
+
return true;
|
|
132
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { defaultPublisher } from './defaultPublisher';
|
|
2
|
+
import { affiliatePort } from './publishers/affiliatePort';
|
|
3
|
+
import { cj } from './publishers/cj';
|
|
4
|
+
import { facebook } from './publishers/facebook';
|
|
5
|
+
import { googleAnalytics4 } from './publishers/googleAnalytics4';
|
|
6
|
+
import { piano } from './publishers/piano';
|
|
7
|
+
import { universalAnalytics } from './publishers/universalAnalytics';
|
|
8
|
+
import * as utils from './utils/utils';
|
|
9
|
+
|
|
10
|
+
export const publisher = {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
12
|
+
Facebook: facebook,
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
14
|
+
CJ: cj,
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
16
|
+
GoogleAnalytics4: googleAnalytics4,
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
18
|
+
UniversalAnalytics: universalAnalytics,
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
20
|
+
Piano: piano,
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
22
|
+
AffiliatePort: affiliatePort,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { utils, defaultPublisher as DefaultPublisher };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as utils from './../utils/utils';
|
|
2
|
+
import {
|
|
3
|
+
PlatformPublisher,
|
|
4
|
+
PlatformRequestOptions,
|
|
5
|
+
} from '../types/PlatformPublisher';
|
|
6
|
+
|
|
7
|
+
interface Product {
|
|
8
|
+
orderId: string;
|
|
9
|
+
quantity: number;
|
|
10
|
+
price: number;
|
|
11
|
+
category: string;
|
|
12
|
+
masterType: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface AffiliatePortData {
|
|
16
|
+
products: Product[];
|
|
17
|
+
orderId: string;
|
|
18
|
+
transactionID: string;
|
|
19
|
+
[x: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const affiliatePort: PlatformPublisher = {
|
|
23
|
+
source: 'AffiliatePort',
|
|
24
|
+
/**
|
|
25
|
+
* Publishes data to AffiliatePort
|
|
26
|
+
* @param log zure Function context.log
|
|
27
|
+
* @param config Publisher configuration
|
|
28
|
+
* @param data Data in publisher-friendly format to be published
|
|
29
|
+
* @param event Event for which the function is triggered
|
|
30
|
+
*/
|
|
31
|
+
async publish(log, config, data, event) {
|
|
32
|
+
if (
|
|
33
|
+
(data as AffiliatePortData).products instanceof Array &&
|
|
34
|
+
(typeof config.offerId === 'string' || typeof config.offerId === 'number')
|
|
35
|
+
) {
|
|
36
|
+
const affiliatePortData = utils.removeUndefined(
|
|
37
|
+
data,
|
|
38
|
+
) as AffiliatePortData;
|
|
39
|
+
|
|
40
|
+
const requestOptions: PlatformRequestOptions = {
|
|
41
|
+
method: 'GET',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const baseUrl = 'https://tracking.affiliateclub.cz/aff_lsr';
|
|
45
|
+
|
|
46
|
+
for (const product of affiliatePortData.products) {
|
|
47
|
+
// https://tracking.affiliateclub.cz/aff_lsr?offer_id=OFFER_ID&adv_sub=TID_SUB_ID&amount=AMOUNT&transaction_id=TRANSACTION_ID&adv_sub2=CATEGORY&adv_sub3=MASTER_TYPE
|
|
48
|
+
const query = `?offer_id=${encodeURIComponent(
|
|
49
|
+
config.offerId,
|
|
50
|
+
)}&adv_sub=TID_${affiliatePortData.orderId}&amount=${
|
|
51
|
+
product.quantity * product.price
|
|
52
|
+
}&transaction_id=${affiliatePortData.transactionID}&adv_sub2=${
|
|
53
|
+
product.category
|
|
54
|
+
}&adv_sub3=${product.masterType}`;
|
|
55
|
+
|
|
56
|
+
await utils.handlePlatformRequest({
|
|
57
|
+
source: this.source,
|
|
58
|
+
baseUrl,
|
|
59
|
+
query,
|
|
60
|
+
requestOptions,
|
|
61
|
+
event,
|
|
62
|
+
logger: log,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
throw new Error('Invalid config for platform ' + this.source);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as utils from './../utils/utils';
|
|
2
|
+
import {
|
|
3
|
+
PlatformPublisher,
|
|
4
|
+
PlatformRequestOptions,
|
|
5
|
+
} from '../types/PlatformPublisher';
|
|
6
|
+
import { TypeSafeObject } from '../types/UtilTypes';
|
|
7
|
+
|
|
8
|
+
interface CjData {
|
|
9
|
+
cjevent?: unknown;
|
|
10
|
+
[x: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const cj: PlatformPublisher = {
|
|
14
|
+
source: 'CJAffiliate',
|
|
15
|
+
/**
|
|
16
|
+
* Publishes data to CJ
|
|
17
|
+
* @param log Azure Function context.log
|
|
18
|
+
* @param config Publisher configuration
|
|
19
|
+
* @param data Data in publisher-friendly format to be published
|
|
20
|
+
* @param event Event for which the function is triggered
|
|
21
|
+
*/
|
|
22
|
+
async publish(log, config, data, event) {
|
|
23
|
+
if (!(data as CjData).cjevent) {
|
|
24
|
+
utils.log(log, 1, `CJ - ${event} - skipped because CJEVENT is missing`);
|
|
25
|
+
// ? Tady se returnoval false, ale nemyslim, ze to neco pouzivalo
|
|
26
|
+
} else {
|
|
27
|
+
if (typeof config.cid === 'string' && typeof config.type === 'string') {
|
|
28
|
+
const cjData = utils.removeUndefined(data) as TypeSafeObject;
|
|
29
|
+
let query = '?cid=' + encodeURI(config.cid);
|
|
30
|
+
query += '&type=' + encodeURI(config.type);
|
|
31
|
+
for (const property in data) {
|
|
32
|
+
if (
|
|
33
|
+
Object.prototype.hasOwnProperty.call(cjData, property) &&
|
|
34
|
+
cjData[property] !== undefined
|
|
35
|
+
) {
|
|
36
|
+
query +=
|
|
37
|
+
'&' +
|
|
38
|
+
encodeURI(property) +
|
|
39
|
+
'=' +
|
|
40
|
+
encodeURI(
|
|
41
|
+
cjData[property] === null
|
|
42
|
+
? ''
|
|
43
|
+
: // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
|
|
44
|
+
(cjData[property]?.toString() as string),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const baseUrl = 'https://www.kdukvh.com/u';
|
|
49
|
+
|
|
50
|
+
const requestOptions: PlatformRequestOptions = {
|
|
51
|
+
method: 'GET',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
await utils.handlePlatformRequest({
|
|
55
|
+
source: this.source,
|
|
56
|
+
baseUrl,
|
|
57
|
+
query,
|
|
58
|
+
requestOptions,
|
|
59
|
+
event,
|
|
60
|
+
logger: log,
|
|
61
|
+
});
|
|
62
|
+
} else {
|
|
63
|
+
throw new Error('Invalid config for platform ' + this.source);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as utils from './../utils/utils';
|
|
2
|
+
import {
|
|
3
|
+
PlatformPublisher,
|
|
4
|
+
PlatformRequestOptions,
|
|
5
|
+
} from '../types/PlatformPublisher';
|
|
6
|
+
|
|
7
|
+
export const facebook: PlatformPublisher = {
|
|
8
|
+
source: 'Faceboook',
|
|
9
|
+
/**
|
|
10
|
+
*Publishes data to Facebook
|
|
11
|
+
* @param log Azure Function context.log
|
|
12
|
+
* @param config Publisher configuration
|
|
13
|
+
* @param data Data in publisher-friendly format to be published
|
|
14
|
+
* @param event Event for which the function is triggered
|
|
15
|
+
*/
|
|
16
|
+
async publish(log, config, data, event) {
|
|
17
|
+
if (
|
|
18
|
+
typeof config.id === 'string' &&
|
|
19
|
+
typeof config.access_token === 'string'
|
|
20
|
+
) {
|
|
21
|
+
const requestOptions: PlatformRequestOptions = {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
body: JSON.stringify({ data: [utils.removeUndefined(data)] }),
|
|
24
|
+
headers: {
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
26
|
+
'Content-Type': 'application/json',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// https://graph.facebook.com/v11.0/<id>/events
|
|
31
|
+
const baseUrl = `https://graph.facebook.com/v11.0/${encodeURIComponent(
|
|
32
|
+
config.id,
|
|
33
|
+
)}/events`;
|
|
34
|
+
|
|
35
|
+
const query = `?access_token=${encodeURI(config.access_token)}`;
|
|
36
|
+
|
|
37
|
+
await utils.handlePlatformRequest({
|
|
38
|
+
source: this.source,
|
|
39
|
+
baseUrl,
|
|
40
|
+
query,
|
|
41
|
+
requestOptions,
|
|
42
|
+
event,
|
|
43
|
+
logger: log,
|
|
44
|
+
});
|
|
45
|
+
} else {
|
|
46
|
+
throw new Error('Invalid config for platform ' + this.source);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as utils from './../utils/utils';
|
|
2
|
+
import {
|
|
3
|
+
PlatformPublisher,
|
|
4
|
+
PlatformRequestOptions,
|
|
5
|
+
} from '../types/PlatformPublisher';
|
|
6
|
+
import { TypeSafeObject } from '../types/UtilTypes';
|
|
7
|
+
|
|
8
|
+
export const googleAnalytics4: PlatformPublisher = {
|
|
9
|
+
source: 'GoogleAnalytics4',
|
|
10
|
+
/**
|
|
11
|
+
* Publishes data to Google Analytics
|
|
12
|
+
* @param log zure Function context.log
|
|
13
|
+
* @param config Publisher configuration
|
|
14
|
+
* @param data Data in publisher-friendly format to be published
|
|
15
|
+
* @param event Event for which the function is triggered
|
|
16
|
+
*/
|
|
17
|
+
async publish(log, config, data, event) {
|
|
18
|
+
if (config.trackingId) {
|
|
19
|
+
const ga4Data = utils.removeUndefined(data) as TypeSafeObject;
|
|
20
|
+
ga4Data.v = 2;
|
|
21
|
+
ga4Data.seg = 1;
|
|
22
|
+
ga4Data.gcs = 111;
|
|
23
|
+
ga4Data.tid = config.trackingId;
|
|
24
|
+
|
|
25
|
+
let payload = '';
|
|
26
|
+
|
|
27
|
+
for (const property in ga4Data) {
|
|
28
|
+
if (Object.prototype.hasOwnProperty.call(ga4Data, property)) {
|
|
29
|
+
if (payload) {
|
|
30
|
+
payload += '&';
|
|
31
|
+
}
|
|
32
|
+
payload += encodeURI(property) + '=' + encodeURI(ga4Data[property]);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const requestOptions: PlatformRequestOptions = {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
40
|
+
'User-Agent': 'mHub Cloud',
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const baseUrl = 'https://www.google-analytics.com/g/collect';
|
|
45
|
+
|
|
46
|
+
const query = `?${payload}`;
|
|
47
|
+
|
|
48
|
+
await utils.handlePlatformRequest({
|
|
49
|
+
source: this.source,
|
|
50
|
+
baseUrl,
|
|
51
|
+
query,
|
|
52
|
+
requestOptions,
|
|
53
|
+
event,
|
|
54
|
+
logger: log,
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
throw new Error('Invalid config for platform ' + this.source);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
};
|