@alexsab-ru/scripts 0.15.3 → 0.16.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/lib/analytics.js +24 -10
- package/lib/calltouch/calltouch-module.js +4 -9
- package/lib/calltouch/create-request.js +76 -53
- package/lib/form.js +57 -5
- package/package.json +1 -1
package/lib/analytics.js
CHANGED
|
@@ -15,17 +15,31 @@ export function reachGoal(eventAction, t = {}) {
|
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
if(window.calltouch_params) {
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
// sendToCallTouch внутри проверяет eventCategory === 'Lead',
|
|
19
|
+
// поэтому вызываем только для лидов, чтобы не делать лишнюю работу.
|
|
20
|
+
if(t.eventCategory === 'Lead') {
|
|
21
|
+
// Если siteId уже задан конкретным дилером (из data-атрибута),
|
|
22
|
+
// не перезатираем его глобальным значением из calltouch_params.
|
|
23
|
+
if(!t.siteId) {
|
|
24
|
+
var rawSiteId = window.calltouch_params.site_id;
|
|
25
|
+
t.siteId = Array.isArray(rawSiteId) ? rawSiteId[0] : rawSiteId;
|
|
26
|
+
}
|
|
27
|
+
// console.log("sendToCallTouch:", t);
|
|
28
|
+
sendToCallTouch(t)
|
|
29
|
+
.then(result => {
|
|
30
|
+
console.log('Данные успешно отправлены в колтач:', eventAction, result);
|
|
31
|
+
})
|
|
32
|
+
.catch(error => {
|
|
33
|
+
console.error('Ошибка при отправке данных в колтач:', eventAction, error);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
27
36
|
if(window.ct) {
|
|
28
|
-
|
|
37
|
+
// mod_id может быть массивом (multi-project) или строкой (legacy).
|
|
38
|
+
var modIds = window.calltouch_params.mod_id;
|
|
39
|
+
var ids = Array.isArray(modIds) ? modIds : [modIds];
|
|
40
|
+
ids.forEach(function(modId) {
|
|
41
|
+
window.ct(modId, 'goal', eventAction);
|
|
42
|
+
});
|
|
29
43
|
}
|
|
30
44
|
}
|
|
31
45
|
ymGoal(eventAction, {
|
|
@@ -98,16 +98,11 @@ function processEventData(eventData, sessionId) {
|
|
|
98
98
|
function sendToCallTouch(options) {
|
|
99
99
|
return new Promise((resolve, reject) => {
|
|
100
100
|
try {
|
|
101
|
-
const { siteId,
|
|
102
|
-
|
|
103
|
-
// Проверяем, что категория события - Lead
|
|
104
|
-
if (eventCategory !== 'Lead') {
|
|
105
|
-
return resolve({ status: 'skipped', message: 'Not a Lead event' });
|
|
106
|
-
}
|
|
107
|
-
|
|
101
|
+
const { siteId, eventProperties, sessionId = window.call_value } = options;
|
|
102
|
+
|
|
108
103
|
// Проверяем обязательные параметры
|
|
109
|
-
if (!siteId) {
|
|
110
|
-
return reject(new Error('siteId is required'));
|
|
104
|
+
if (!siteId || typeof siteId !== 'string') {
|
|
105
|
+
return reject(new Error('siteId is required and must be a string'));
|
|
111
106
|
}
|
|
112
107
|
|
|
113
108
|
// Обрабатываем данные с помощью оптимизированной функции
|
|
@@ -1,8 +1,75 @@
|
|
|
1
|
-
export const createRequest = (routeKey, phoneValue, nameValue, verbose = false) => {
|
|
2
|
-
return new Promise((resolve, reject) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export const createRequest = (routeKey, phoneValue, nameValue, verbose = false, modId = '') => {
|
|
2
|
+
return new Promise((resolve, reject) => {
|
|
3
|
+
let errorText = '';
|
|
4
|
+
|
|
5
|
+
// Если mod_id передан явно, пытаемся взять выделенный инстанс multi-project:
|
|
6
|
+
// window["ctw_<mod_id>"].
|
|
7
|
+
const scopedKey = modId ? `ctw_${modId}` : '';
|
|
8
|
+
const scopedCtw = scopedKey && window[scopedKey] ? window[scopedKey] : null;
|
|
9
|
+
// Fallback для старого сценария, где есть только один глобальный инстанс.
|
|
10
|
+
const fallbackCtw = window.ctw || null;
|
|
11
|
+
const ctwInstance = scopedCtw || fallbackCtw;
|
|
12
|
+
|
|
13
|
+
if (!ctwInstance || typeof ctwInstance.createRequest !== 'function') {
|
|
14
|
+
reject('window.ctw is not defined');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const executeCreateRequest = () => {
|
|
19
|
+
let phone_ct = phoneValue.replace(/[^0-9]/gim, '');
|
|
20
|
+
if (phone_ct[0] == '8') { phone_ct = phone_ct.substring(1); }
|
|
21
|
+
if (phone_ct[0] == '7') { phone_ct = phone_ct.substring(1); }
|
|
22
|
+
phone_ct = '7' + phone_ct;
|
|
23
|
+
|
|
24
|
+
ctwInstance.createRequest(
|
|
25
|
+
routeKey,
|
|
26
|
+
phone_ct,
|
|
27
|
+
(nameValue.length > 0 ? [{ "name": "Name", "value": nameValue }] : []),
|
|
28
|
+
function(success, data) {
|
|
29
|
+
verbose && console.log(success, data);
|
|
30
|
+
if (success) {
|
|
31
|
+
verbose && console.log('Создана заявка на колбек, идентификатор: ' + data.callbackRequestId);
|
|
32
|
+
resolve(data);
|
|
33
|
+
} else {
|
|
34
|
+
errorText = 'Error in createRequest';
|
|
35
|
+
switch (data.type) {
|
|
36
|
+
case 'request_throttle_timeout':
|
|
37
|
+
case 'request_throttle_count':
|
|
38
|
+
errorText = 'Достигнут лимит создания заявок, попробуйте позже';
|
|
39
|
+
verbose && console.log(errorText);
|
|
40
|
+
break;
|
|
41
|
+
case 'request_phone_blacklisted':
|
|
42
|
+
errorText = 'номер телефона находится в черном списке';
|
|
43
|
+
verbose && console.log(errorText);
|
|
44
|
+
break;
|
|
45
|
+
case 'validation_error':
|
|
46
|
+
errorText = 'были переданы некорректные данные';
|
|
47
|
+
verbose && console.log(errorText);
|
|
48
|
+
break;
|
|
49
|
+
default:
|
|
50
|
+
errorText = 'Во время выполнения запроса произошла ошибка: ' + data.type;
|
|
51
|
+
verbose && console.log(errorText);
|
|
52
|
+
}
|
|
53
|
+
reject(errorText);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Multi-project: если нашли window["ctw_<mod_id>"], сразу создаём заявку.
|
|
60
|
+
// Здесь намеренно пропускаем getRouteKeyData.
|
|
61
|
+
if (scopedCtw) {
|
|
62
|
+
executeCreateRequest();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Legacy-ветка: без mod_id сохраняем исходную проверку routeKey через getRouteKeyData.
|
|
67
|
+
if (typeof ctwInstance.getRouteKeyData !== 'function') {
|
|
68
|
+
reject('window.ctw.getRouteKeyData is not defined');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ctwInstance.getRouteKeyData(routeKey, function(success, data) {
|
|
6
73
|
verbose && console.log(success, data);
|
|
7
74
|
if (success) {
|
|
8
75
|
if (data.widgetFound) {
|
|
@@ -15,62 +82,18 @@ return new Promise((resolve, reject) => {
|
|
|
15
82
|
verbose && console.log('колл-центр не работает, заявки в нерабочее время не собираем');
|
|
16
83
|
}
|
|
17
84
|
}
|
|
18
|
-
|
|
19
|
-
var phone_ct = phoneValue.replace(/[^0-9]/gim, '');
|
|
20
|
-
if (phone_ct[0] == '8') { phone_ct = phone_ct.substring(1); }
|
|
21
|
-
if (phone_ct[0] == '7') { phone_ct = phone_ct.substring(1); }
|
|
22
|
-
phone_ct = '7' + phone_ct;
|
|
23
|
-
|
|
24
|
-
window.ctw.createRequest(
|
|
25
|
-
routeKey,
|
|
26
|
-
phone_ct,
|
|
27
|
-
( nameValue.length > 0 ? [
|
|
28
|
-
{"name": "Name", "value": nameValue}
|
|
29
|
-
] : []),
|
|
30
|
-
function (success, data) {
|
|
31
|
-
verbose && console.log(success, data)
|
|
32
|
-
if (success) {
|
|
33
|
-
verbose && console.log('Создана заявка на колбек, идентификатор: ' + data.callbackRequestId);
|
|
34
|
-
resolve(data); // Разрешаем Promise данными от createRequest
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
errorText = 'Error in createRequest';
|
|
38
|
-
switch (data.type) {
|
|
39
|
-
case "request_throttle_timeout":
|
|
40
|
-
case "request_throttle_count":
|
|
41
|
-
errorText = 'Достигнут лимит создания заявок, попробуйте позже';
|
|
42
|
-
verbose && console.log(errorText);
|
|
43
|
-
break;
|
|
44
|
-
case "request_phone_blacklisted":
|
|
45
|
-
errorText = 'номер телефона находится в черном списке';
|
|
46
|
-
verbose && console.log(errorText);
|
|
47
|
-
break;
|
|
48
|
-
case "validation_error":
|
|
49
|
-
errorText = 'были переданы некорректные данные';
|
|
50
|
-
verbose && console.log(errorText);
|
|
51
|
-
break;
|
|
52
|
-
default:
|
|
53
|
-
errorText = 'Во время выполнения запроса произошла ошибка: ' + data.type;
|
|
54
|
-
verbose && console.log(errorText);
|
|
55
|
-
}
|
|
56
|
-
reject(errorText); // Отклоняем Promise в случае ошибки
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
);
|
|
85
|
+
executeCreateRequest();
|
|
60
86
|
} else {
|
|
61
|
-
errorText = 'не найден включенный виджет '+routeKey+', либо услуга обратного звонка не активна';
|
|
87
|
+
errorText = 'не найден включенный виджет ' + routeKey + ', либо услуга обратного звонка не активна';
|
|
62
88
|
verbose && console.log(errorText);
|
|
63
89
|
reject(errorText);
|
|
64
90
|
}
|
|
65
91
|
} else {
|
|
66
92
|
errorText = 'во время обработки произошла ошибка';
|
|
67
93
|
verbose && console.log(errorText);
|
|
68
|
-
verbose && console.log(data)
|
|
94
|
+
verbose && console.log(data);
|
|
69
95
|
reject(errorText);
|
|
70
96
|
}
|
|
71
97
|
});
|
|
72
|
-
}
|
|
73
|
-
reject("window.ctw is not defined");
|
|
74
|
-
}
|
|
75
|
-
});
|
|
98
|
+
});
|
|
76
99
|
};
|
package/lib/form.js
CHANGED
|
@@ -122,6 +122,8 @@ export const messageModal = document.getElementById("message-modal");
|
|
|
122
122
|
export const connectForms = (url, props = propsParams) => {
|
|
123
123
|
props = {...propsParams, ...props};
|
|
124
124
|
|
|
125
|
+
console.log("url: ", url);
|
|
126
|
+
console.log("props: ", props);
|
|
125
127
|
|
|
126
128
|
document.querySelectorAll("input[name=phone]").forEach(function (element) {
|
|
127
129
|
// element.addEventListener("focus", maskphone);
|
|
@@ -290,21 +292,71 @@ const submitForm = async (form) => {
|
|
|
290
292
|
});
|
|
291
293
|
|
|
292
294
|
let formDataObj = {};
|
|
295
|
+
// Считаем значения один раз, чтобы одинаково использовать их в try/catch и логах.
|
|
296
|
+
const dealerRouteKey = dealer && dealer.dataset ? (dealer.dataset.ctRouteKey || '').trim() : '';
|
|
297
|
+
const dealerModId = dealer && dealer.dataset ? (dealer.dataset.ctModId || '').trim() : '';
|
|
298
|
+
const dealerSiteId = dealer && dealer.dataset ? (dealer.dataset.ctSiteId || '').trim() : '';
|
|
299
|
+
const calltouchRouteKey = dealerRouteKey || props.ct_routeKey;
|
|
300
|
+
const scopedCtwName = dealerModId ? `ctw_${dealerModId}` : '';
|
|
301
|
+
const hasScopedCtw = scopedCtwName ? typeof window[scopedCtwName] !== 'undefined' : false;
|
|
302
|
+
const hasGlobalCtw = typeof window.ctw !== 'undefined';
|
|
303
|
+
|
|
293
304
|
try {
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
305
|
+
// Для multi-project берём routeKey/mod_id у выбранного дилера (data-атрибуты select).
|
|
306
|
+
// Если дилерские значения отсутствуют, используем старый глобальный props.ct_routeKey.
|
|
307
|
+
props.verbose && console.log('Calltouch submit debug:', {
|
|
308
|
+
formId: form.id || '',
|
|
309
|
+
phone: phone && phone.value ? phone.value : '',
|
|
310
|
+
name: name && name.value ? name.value : '',
|
|
311
|
+
dealerValue: dealer && dealer.value ? dealer.value : '',
|
|
312
|
+
dealerRouteKey,
|
|
313
|
+
dealerModId,
|
|
314
|
+
dealerSiteId,
|
|
315
|
+
fallbackRouteKey: props.ct_routeKey,
|
|
316
|
+
calltouchRouteKey,
|
|
317
|
+
scopedCtwName,
|
|
318
|
+
hasScopedCtw,
|
|
319
|
+
hasGlobalCtw
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// Отправка заявки на обратный вызов в CallTouch.
|
|
323
|
+
if(calltouchRouteKey != '') {
|
|
324
|
+
const requestData = await createRequest(calltouchRouteKey, phone.value, name.value, props.verbose, dealerModId);
|
|
297
325
|
formData.append("ct_callback", true);
|
|
298
326
|
formData.append("ctw_createRequest", JSON.stringify(requestData));
|
|
327
|
+
if (dealerModId !== '') {
|
|
328
|
+
// Храним mod_id в payload для отладки и серверных логов.
|
|
329
|
+
formData.append("ct_mod_id", dealerModId);
|
|
330
|
+
}
|
|
299
331
|
} else {
|
|
300
332
|
throw new Error('Empty ct_routeKey');
|
|
301
333
|
}
|
|
302
334
|
} catch (error) {
|
|
303
|
-
if(
|
|
335
|
+
if(calltouchRouteKey != '') {
|
|
304
336
|
formData.append("ctw_createRequest", error);
|
|
305
337
|
}
|
|
306
|
-
|
|
338
|
+
const normalizedError = error instanceof Error ? {
|
|
339
|
+
name: error.name,
|
|
340
|
+
message: error.message,
|
|
341
|
+
stack: error.stack
|
|
342
|
+
} : error;
|
|
343
|
+
console.error("Error during request Calltouch callback:", normalizedError, {
|
|
344
|
+
formId: form.id || '',
|
|
345
|
+
dealerRouteKey,
|
|
346
|
+
dealerModId,
|
|
347
|
+
dealerSiteId,
|
|
348
|
+
fallbackRouteKey: props.ct_routeKey,
|
|
349
|
+
calltouchRouteKey,
|
|
350
|
+
scopedCtwName,
|
|
351
|
+
hasScopedCtw,
|
|
352
|
+
hasGlobalCtw
|
|
353
|
+
});
|
|
307
354
|
formDataObj = getFormDataObject(formData, form.id);
|
|
355
|
+
// Если известен конкретный siteId дилера, прокидываем его,
|
|
356
|
+
// чтобы reachGoal → sendToCallTouch отправил лид в нужный проект.
|
|
357
|
+
if (dealerSiteId) {
|
|
358
|
+
formDataObj.siteId = dealerSiteId;
|
|
359
|
+
}
|
|
308
360
|
}
|
|
309
361
|
|
|
310
362
|
const params = new URLSearchParams([...formData]);
|