Цели Яндекс.Метрики через API: автоматизация вместо ручной настройки
Основной чат
Чат для вайбкодеров: новости, гайды, поиск исполнителей, маркетплейс и разбор реальных кейсов.
Обычный путь настройки целей в Яндекс.Метрике выглядит так: зайти в интерфейс, нажать «Добавить цель», ввести название, выбрать тип, сохранить. Повторить 15 раз. Потом при переезде на другой счётчик — повторить всё снова. Если в команде несколько проектов — повторить для каждого.
Есть способ лучше. Яндекс.Метрика предоставляет Management API, через которое можно создавать цели программно — скриптом, за секунды, без интерфейса. Один раз написал скрипт, добавил в package.json, и теперь синхронизация целей запускается одной командой.
Разбираем как это работает и как сделать самому.
Зачем автоматизировать цели
Воспроизводимость. Список целей живёт в коде рядом с проектом. Новый разработчик клонирует репозиторий, запускает скрипт — и счётчик настроен. Никаких «а кто помнит что мы отслеживали?».
Пересинхронизация. Если счётчик слетел, нужно завести новый или скопировать цели на другой счётчик — запускаете скрипт с другим COUNTER_ID и готово.
Версионирование. Список целей в git-репозитории — видно когда добавили новую цель, кто и зачем.
Защита от дублей. Скрипт сначала запрашивает текущие цели и создаёт только те, которых ещё нет.
Как это работает: схема
npm run metrica:goals
│
▼
Скрипт читает YANDEX_METRICA_TOKEN и COUNTER_ID из .env
│
▼
GET /management/v1/counter/{id}/goals ← текущие цели в Метрике
│
▼
Сравнение с нужным списком целей в коде
│
├── Цель уже есть → пропустить
└── Цели нет → POST /management/v1/counter/{id}/goals/ ← создать
Скрипт никогда не удаляет существующие цели — только добавляет новые. Безопасно запускать повторно сколько угодно раз.
Шаг 1. Получите OAuth-токен Яндекса
Для работы с Management API нужен OAuth-токен. Это не логин/пароль, а специальный ключ для API.
Зарегистрируйте приложение
- Откройте oauth.yandex.ru
- Нажмите «Зарегистрировать новое приложение»
- Название — любое, например «Metrica Goals Sync»
- Платформа — «Веб-сервисы»
- Redirect URI —
https://oauth.yandex.ru/verification_code - Доступы — найдите раздел «Яндекс.Метрика», включите
metrika:write
После регистрации получите client_id.
Получите токен
Откройте в браузере:
https://oauth.yandex.ru/authorize?response_type=token&client_id=ВАШ_CLIENT_ID
Авторизуйтесь, разрешите доступ — в адресной строке появится токен вида y0_AgAAAA.... Скопируйте его.
Сохраните в .env
# .env (не коммитить в git!)
YANDEX_METRICA_TOKEN=y0_AgAAAA...
YANDEX_METRICA_COUNTER_ID=ВАШ_НОМЕР_СЧЁТЧИКА
Номер счётчика виден в URL когда вы открываете счётчик в интерфейсе Метрики.
Шаг 2. Напишите скрипт синхронизации
// scripts/yandex-metrica-goals.mjs
const TOKEN = process.env.YANDEX_METRICA_TOKEN;
const COUNTER_ID = process.env.YANDEX_METRICA_COUNTER_ID;
if (!TOKEN || !COUNTER_ID) {
console.error('❌ Укажите YANDEX_METRICA_TOKEN и YANDEX_METRICA_COUNTER_ID');
process.exit(1);
}
const BASE_URL = `https://api-metrika.yandex.net/management/v1/counter/${COUNTER_ID}`;
const HEADERS = {
'Authorization': `OAuth ${TOKEN}`,
'Content-Type': 'application/json',
};
// ─── Список нужных целей ──────────────────────────────────────────────────────
//
// type: 'action' — JavaScript-событие через ym(id, 'reachGoal', 'goal_name')
// Поле conditions[0].value — это 'goal_name' в вашем reachGoal()
//
const DESIRED_GOALS = [
{
name: 'Открытие статьи',
type: 'action',
conditions: [{ type: 'exact', value: 'article_open' }],
},
{
name: 'Клик по CTA',
type: 'action',
conditions: [{ type: 'exact', value: 'cta_click' }],
},
{
name: 'Поиск по сайту',
type: 'action',
conditions: [{ type: 'exact', value: 'search' }],
},
{
name: 'Переход в Telegram',
type: 'action',
conditions: [{ type: 'exact', value: 'telegram_click' }],
},
{
name: 'Добавление в закладки',
type: 'action',
conditions: [{ type: 'exact', value: 'bookmark_add' }],
},
// Добавляйте свои цели сюда
];
// ─── Вспомогательные функции ──────────────────────────────────────────────────
async function getExistingGoals() {
const res = await fetch(`${BASE_URL}/goals`, { headers: HEADERS });
if (!res.ok) {
const err = await res.text();
throw new Error(`Ошибка получения целей: ${res.status} ${err}`);
}
const data = await res.json();
return data.goals || [];
}
async function createGoal(goal) {
const res = await fetch(`${BASE_URL}/goals/`, {
method: 'POST',
headers: HEADERS,
body: JSON.stringify({ goal }),
});
if (!res.ok) {
const err = await res.text();
throw new Error(`Ошибка создания цели "${goal.name}": ${res.status} ${err}`);
}
return res.json();
}
// ─── Основная логика ──────────────────────────────────────────────────────────
async function syncGoals() {
console.log(`\n🔄 Синхронизация целей для счётчика ${COUNTER_ID}\n`);
// 1. Получаем текущие цели
const existingGoals = await getExistingGoals();
console.log(`📊 Текущих целей в Метрике: ${existingGoals.length}`);
// Собираем Set названий для быстрого поиска
const existingNames = new Set(existingGoals.map(g => g.name));
// 2. Создаём только отсутствующие
let created = 0;
let skipped = 0;
for (const goal of DESIRED_GOALS) {
if (existingNames.has(goal.name)) {
console.log(` ⏭️ Пропущена (уже есть): ${goal.name}`);
skipped++;
continue;
}
try {
await createGoal(goal);
console.log(` ✅ Создана: ${goal.name}`);
created++;
} catch (err) {
console.error(` ❌ ${err.message}`);
}
// Небольшая пауза чтобы не спамить API
await new Promise(r => setTimeout(r, 300));
}
console.log(`\n✨ Готово! Создано: ${created}, пропущено: ${skipped}\n`);
}
syncGoals().catch(err => {
console.error('Критическая ошибка:', err.message);
process.exit(1);
});
Шаг 3. Добавьте команду в package.json
{
"scripts": {
"metrica:goals": "node scripts/yandex-metrica-goals.mjs"
}
}
Теперь синхронизация запускается так:
npm run metrica:goals
Шаг 4. Отправляйте события со страниц
Цели в Метрике — это только «ловушки». Чтобы они срабатывали, нужно отправлять события с сайта через ym().
Убедитесь что счётчик установлен
<!-- В <head> каждой страницы -->
<script>
(function(m,e,t,r,i,k,a){
m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
// ... стандартный код счётчика Метрики
})(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(ВАШ_COUNTER_ID, "init", { clickmap: true, trackLinks: true });
</script>
Отправка события
// Синтаксис
ym(COUNTER_ID, 'reachGoal', 'goal_name');
// Примеры — значение 'goal_name' должно совпадать
// с conditions[0].value в вашем скрипте
ym(12345678, 'reachGoal', 'article_open');
ym(12345678, 'reachGoal', 'cta_click');
ym(12345678, 'reachGoal', 'search');
Реальные примеры интеграции
// Открытие статьи — при монтировании компонента
useEffect(() => {
ym(COUNTER_ID, 'reachGoal', 'article_open');
}, []);
// Клик по CTA-кнопке
function handleCtaClick() {
ym(COUNTER_ID, 'reachGoal', 'cta_click');
// ... остальная логика
}
// Поиск — при отправке формы
function handleSearch(query) {
if (query.length > 2) {
ym(COUNTER_ID, 'reachGoal', 'search');
}
}
// Переход в Telegram
function handleTelegramLink() {
ym(COUNTER_ID, 'reachGoal', 'telegram_click');
}
// Добавление в закладки
function handleBookmark(articleId) {
ym(COUNTER_ID, 'reachGoal', 'bookmark_add');
saveBookmark(articleId);
}
Полная схема работы
Пользователь открыл статью
│
▼
useEffect → ym(id, 'reachGoal', 'article_open')
│
▼
Яндекс.Метрика засчитала цель "Открытие статьи"
│
▼
Видно в отчётах Метрики → Конверсии → Цели
Всё что связывает клиентский код с настройками Метрики — строка 'article_open'. Именно поэтому важно чтобы значение в conditions[0].value в скрипте совпадало с тем что вы передаёте в reachGoal().
Типы целей в API
В скрипте используется тип action — это JavaScript-событие через reachGoal. Но API поддерживает и другие типы:
| Тип | Когда использовать | Пример |
|---|---|---|
action |
JS-событие через reachGoal | Клик по кнопке |
url |
Посещение URL | Страница /thank-you |
request |
Запрос к URL | Файл .pdf скачан |
step |
Составная цель (шаги) | Воронка оформления заказа |
Для url и request тип условия будет другим:
// Цель по URL
{
name: 'Страница благодарности',
type: 'url',
conditions: [{ type: 'contain', value: '/thank-you' }],
}
// Цель по скачиванию файла
{
name: 'Скачан прайс-лист',
type: 'request',
conditions: [{ type: 'contain', value: 'price-list.pdf' }],
}
Запуск с явными переменными
Если .env не настроен или нужно запустить для другого счётчика:
# Экспортировать переменные из .env и запустить
set -a && source .env && set +a
YANDEX_METRICA_COUNTER_ID=другой_счётчик npm run metrica:goals
# Или передать переменные напрямую
YANDEX_METRICA_TOKEN=токен YANDEX_METRICA_COUNTER_ID=123456 npm run metrica:goals
Что добавить в .gitignore
# Токены и секреты — никогда в репозиторий
.env
.env.local
.env.*.local
Сам скрипт yandex-metrica-goals.mjs — коммитить можно и нужно: в нём нет секретов, только логика и список целей.
Итог
Автоматизация целей через API решает три проблемы сразу: воспроизводимость (список целей в коде), безопасность повторного запуска (нет дублей, нет удалений) и скорость (секунды вместо ручной настройки через интерфейс).
Схема простая: скрипт знает какие цели должны быть, спрашивает Метрику какие есть, создаёт разницу. Сайт отправляет события через ym(id, 'reachGoal', 'название'). Метрика засчитывает конверсии.
Один раз настроили — и больше не думаете о ручной настройке целей при смене счётчика или добавлении нового проекта.