Перехват AJAX с помощью функции fetch (GET)

2025-05-06

В этой статье мы рассмотрим код, который перехватывает AJAX-запросы (метод GET), отправляемые с помощью функции fetch, и выполняет определенные действия при успешном добавлении товара в корзину или отправки формы обратной связи.

Пример ajax (метод GET) на сайте wordpress

По нажатию на кнопку делаем запрос на добавление товара в корзину.
В консоли разработчика запрос будет выглядеть так: /wp-admin/admin-ajax.php?method=add_item
И мы хотим выполнить Яндекс-цель, если находим в URL строку method=add_item.

Код

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/* Константы для определения событий */
const SUCCESS_STATUS = 200;
const ADD_ITEM_METHOD_ID = 'method=add_item';
const ADD_ITEM_METHOD_NAME = 'addItem';
const YM_TARGET = 'product-add-to-cart';

/* Список отслеживаемых URL */
const trackedUrls = [
{
id: ADD_ITEM_METHOD_ID,
method: ADD_ITEM_METHOD_NAME,
ymTarget: YM_TARGET,
}
];

/* Сохраняем оригинальную функцию fetch */
const originalFetch = window.fetch;

/* Переопределяем функцию fetch для перехвата запросов */
window.fetch = function(...args) {
return originalFetch.apply(this, args).then(response => {
const clonedResponse = response.clone();
const responseUrl = clonedResponse.url;

/* Проверяем каждый элемент в списке отслеживаемых URL */
for (const trackedUrl of trackedUrls) {
try {
if (clonedResponse.status === SUCCESS_STATUS && responseUrl.includes(trackedUrl.id)) {
analyticsMethods[trackedUrl.method](trackedUrl.ymTarget);
}
} catch (error) {
console.error("Error processing request:", error);
}
}

return response;
});
};

/* Функция для работы с Яндекс.Метрикой */
const createAnalyticsMethods = (ymId) => {
return {
addItem: (targetId) => {
ym(ymId, 'reachGoal', targetId);
console.log('Yandex.Metrica target:', targetId);
}
};
};

/* Инициализация методов аналитики */
const analyticsMethods = createAnalyticsMethods(12345678);

Объяснение кода

1. Определение констант

1
2
3
4
const SUCCESS_STATUS = 200;
const ADD_ITEM_METHOD_ID = 'method=add_item';
const ADD_ITEM_METHOD_NAME = 'addItem';
const YM_TARGET = 'product-add-to-cart';

Здесь мы определяем константы, которые используются в коде. Это улучшает читаемость и позволяет избежать “магических строк”. Константы включают:

  • SUCCESS_STATUS: статус ответа, указывающий на успешное выполнение запроса.
  • ADD_ITEM_METHOD_ID: уникальный идентификатор для метода добавления товара.
  • ADD_ITEM_METHOD_NAME: название метода, который будет вызван для обработки события.
  • YM_TARGET: цель, которая будет передана в аналитику.

2. Список отслеживаемых URL

1
2
3
4
5
6
7
const trackedUrls = [
{
id: ADD_ITEM_METHOD_ID,
method: ADD_ITEM_METHOD_NAME,
ymTarget: YM_TARGET,
}
];

Мы создаем массив объектов trackedUrls, который содержит информацию о том, какие запросы мы будем отслеживать. Каждый объект включает идентификатор, метод и цель для аналитики.

3. Сохранение оригинальной функции fetch

1
const originalFetch = window.fetch;

Мы сохраняем оригинальную функцию fetch в переменной originalFetch, чтобы иметь возможность вызывать её позже.

4. Переопределение функции fetch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
window.fetch = function(...args) {
return originalFetch.apply(this, args).then(response => {
const clonedResponse = response.clone();
const responseUrl = clonedResponse.url;

/* Проверяем каждый элемент в списке отслеживаемых URL */
for (const trackedUrl of trackedUrls) {
try {
if (clonedResponse.status === SUCCESS_STATUS && responseUrl.includes(trackedUrl.id)) {

/* Это динамическое обращение к методу в объекте analyticsMethods */
analyticsMethods[trackedUrl.method](trackedUrl.ymTarget);
}
} catch (error) {
console.error("Error processing request:", error);
}
}

return response;
});
};

Мы переопределяем метод fetch, чтобы добавить логику обработки после выполнения запроса. Внутри переопределенной функции:

  • Клонирование ответа: Мы создаем клон ответа с помощью response.clone(), так как объект Response может быть прочитан только один раз.
  • Получение URL: Из клонированного ответа извлекаем URL запроса.
  • Цикл по trackedUrls: Мы проходим по всем элементам в trackedUrls и проверяем, соответствует ли статус ответа значению SUCCESS_STATUS и содержится ли идентификатор в URL.
  • Вызов метода: Если оба условия выполняются, вызываем метод, указанный в trackedUrl.method, передавая ему trackedUrl.ymTarget как аргумент.
  • Обработка ошибок: Ошибки, возникающие в процессе выполнения, логируются в консоль.

5. Функция для работы с Яндекс.Метрикой

1
2
3
4
5
6
7
8
const createAnalyticsMethods = (ymId) => {
return {
addItem: (targetId) => {
ym(ymId, 'reachGoal', targetId);
console.log('Yandex.Metrica target:', targetId);
}
};
};

Функция createAnalyticsMethods создает объект с методами для работы с Яндекс.Метрикой. В данном случае мы определяем метод addItem, который будет вызываться, когда товар добавляется в корзину. Он принимает targetId и вызывает функцию ym, передавая ей идентификатор Яндекс.Метрики, цель и идентификатор товара.

6. Инициализация analyticsMethods

1
const analyticsMethods = createAnalyticsMethods(12345678);

Здесь мы создаем объект analyticsMethods, вызывая функцию createAnalyticsMethods с идентификатором Яндекс.Метрики (в данном случае 12345678).

Итог

В результате, каждый раз, когда происходит успешный AJAX-запрос на добавление товара в корзину, отправки формы и тд., вызывается соответствующий метод для отслеживания этого события в Яндекс.Метрике.