@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 CHANGED
@@ -15,17 +15,31 @@ export function reachGoal(eventAction, t = {}) {
15
15
  });
16
16
  }
17
17
  if(window.calltouch_params) {
18
- t.siteId = window.calltouch_params.site_id;
19
- // console.log("sendToCallTouch:", t);
20
- sendToCallTouch(t)
21
- .then(result => {
22
- console.log('Данные успешно отправлены в колтач:', eventAction, result);
23
- })
24
- .catch(error => {
25
- console.error('Ошибка при отправке данных в колтач:', eventAction, error);
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
- window.ct(window.calltouch_params.mod_id, 'goal', eventAction);
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, eventCategory, eventProperties, sessionId = window.call_value } = options;
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
- let errorText = '';
4
- if(window.ctw) {
5
- window.ctw.getRouteKeyData(routeKey, function(success, data){
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
- } else {
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
- // Отправка заявки на обратный возов в CallTouch
295
- if(props.ct_routeKey != '') {
296
- const requestData = await createRequest(props.ct_routeKey, phone.value, name.value, props.verbose);
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(props.ct_routeKey != '') {
335
+ if(calltouchRouteKey != '') {
304
336
  formData.append("ctw_createRequest", error);
305
337
  }
306
- props.verbose && console.error("Error during request Calltouch callback:", error);
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]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexsab-ru/scripts",
3
- "version": "0.15.3",
3
+ "version": "0.16.1",
4
4
  "description": "common libs for websites",
5
5
  "main": "index.js",
6
6
  "scripts": {