@ezmar/yandex-metric-parser-lib 0.1.0

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.
@@ -0,0 +1,999 @@
1
+ /**
2
+ * Ошибки API Метрики.
3
+ *
4
+ * Тело ошибки: `{ errors: [{ error_type, message, location }], code, message }`.
5
+ * Типы ошибок описаны в разделе «Описание ошибок в API».
6
+ */
7
+ /** Один элемент массива `errors` в ответе API. */
8
+ interface ApiErrorDetail {
9
+ error_type: string;
10
+ message?: string;
11
+ location?: string;
12
+ }
13
+ /** Тело ошибочного ответа API Метрики. */
14
+ interface ApiErrorBody {
15
+ errors?: ApiErrorDetail[];
16
+ code?: number;
17
+ message?: string;
18
+ }
19
+ /** Базовая ошибка API Метрики. */
20
+ declare class MetrikaError extends Error {
21
+ readonly status: number;
22
+ readonly errorType: string;
23
+ readonly details: ApiErrorDetail[];
24
+ readonly requestUrl: string;
25
+ constructor(message: string, options: {
26
+ status: number;
27
+ errorType: string;
28
+ details: ApiErrorDetail[];
29
+ requestUrl: string;
30
+ });
31
+ }
32
+ /** 429: превышена одна из квот. Запрос имеет смысл повторить позже. */
33
+ declare class QuotaError extends MetrikaError {
34
+ /** Через сколько миллисекунд разумно повторить попытку. */
35
+ readonly retryAfterMs: number;
36
+ constructor(message: string, options: ConstructorParameters<typeof MetrikaError>[1] & {
37
+ retryAfterMs: number;
38
+ });
39
+ }
40
+ /** 401/403: нет токена, токен недействителен или нет доступа к счётчику. */
41
+ declare class AuthError extends MetrikaError {
42
+ }
43
+ /** 400: неверный параметр запроса — обычно исчезнувшая или опечатанная группировка. */
44
+ declare class InvalidRequestError extends MetrikaError {
45
+ }
46
+ /** 404: объект не найден. */
47
+ declare class NotFoundError extends MetrikaError {
48
+ }
49
+ /** 5xx и 504: временная проблема на стороне сервиса. */
50
+ declare class ServerError extends MetrikaError {
51
+ }
52
+ /** Ошибка валидации запроса на стороне библиотеки — до обращения к API. */
53
+ declare class RequestValidationError extends Error {
54
+ constructor(message: string);
55
+ }
56
+ /** Строит типизированную ошибку по HTTP-статусу и телу ответа. */
57
+ declare function toMetrikaError(status: number, body: ApiErrorBody | undefined, requestUrl: string): MetrikaError;
58
+ /** Стоит ли повторять запрос после этой ошибки. */
59
+ declare function isRetryable(error: unknown): boolean;
60
+
61
+ /**
62
+ * Локальный лимитер под квоты Яндекс Метрики.
63
+ *
64
+ * Квоты из раздела «Квотирование»:
65
+ * - 30 запросов в секунду с одного IP;
66
+ * - 3 параллельных запроса на пользователя;
67
+ * - 5000 запросов в сутки на пользователя (сброс в 00:00 GMT);
68
+ * - 200 запросов за 5 минут к `/stat/v1/data`.
69
+ *
70
+ * Дешевле подождать локально, чем словить 429 и потерять запрос.
71
+ */
72
+ /** Группа методов: отчёты считаются отдельной пятиминутной квотой. */
73
+ type QuotaScope = 'report' | 'management';
74
+ interface RateLimitOptions {
75
+ /** Одновременных запросов. По умолчанию 3 — квота на пользователя. */
76
+ maxConcurrent?: number;
77
+ /** Запросов в секунду. По умолчанию 30 — квота на IP. */
78
+ perSecond?: number;
79
+ /** Запросов к `/stat/v1/data` за 5 минут. По умолчанию 200. */
80
+ reportsPer5Min?: number;
81
+ /** Запросов в сутки. По умолчанию 5000, сброс в 00:00 GMT. */
82
+ perDay?: number;
83
+ /** Подменяемый источник времени и сна — для тестов. */
84
+ now?: () => number;
85
+ sleep?: (ms: number) => Promise<void>;
86
+ }
87
+ declare class RateLimiter {
88
+ private readonly maxConcurrent;
89
+ private readonly perSecond;
90
+ private readonly reportsPer5Min;
91
+ private readonly perDay;
92
+ private readonly now;
93
+ private readonly sleep;
94
+ private inFlight;
95
+ private readonly secondWindow;
96
+ private readonly reportWindow;
97
+ private dayKey;
98
+ private dayCount;
99
+ /** Очередь ожидающих: разбуженные проверяют условия заново. */
100
+ private readonly waiters;
101
+ constructor(options?: RateLimitOptions);
102
+ /** Выполняет `fn`, не нарушая квот. Возвращает результат `fn`. */
103
+ schedule<T>(scope: QuotaScope, fn: () => Promise<T>): Promise<T>;
104
+ /** Сколько запросов уже израсходовано в текущих окнах — для диагностики. */
105
+ usage(): {
106
+ inFlight: number;
107
+ lastSecond: number;
108
+ reportsLast5Min: number;
109
+ today: number;
110
+ };
111
+ private rollDay;
112
+ private acquire;
113
+ /** 0 — можно выполнять; Infinity — ждать освобождения слота параллелизма. */
114
+ private waitMs;
115
+ private release;
116
+ }
117
+
118
+ /**
119
+ * Предупреждения, которые библиотека выдаёт вместо тихого проглатывания проблемы.
120
+ *
121
+ * Ни одно из них не является ошибкой запроса: данные пришли, но их нужно читать с оговоркой.
122
+ */
123
+ type WarningCode =
124
+ /** Ответ построен по неполной выборке — редкие фразы могли не попасть в отчёт. */
125
+ 'sampling'
126
+ /** Часть строк скрыта порогом приватности: фразы не отдаются при выборке < 10 посетителей. */
127
+ | 'sensitive_data_hidden'
128
+ /** Данные за хвост периода ещё дозаполняются. */
129
+ | 'data_lag'
130
+ /** Запрошена модель атрибуции, которая с 25.06.2026 схлопывается в аналог. */
131
+ | 'deprecated_attribution'
132
+ /** API вернул группировку или метрику, которой нет в снапшоте контракта. */
133
+ | 'unknown_field'
134
+ /** Достигнут предел выдачи — часть строк осталась за пределами выгрузки. */
135
+ | 'truncated'
136
+ /** Нет доступа к кампаниям Директа: клики и расходы недоступны. */
137
+ | 'direct_access_missing';
138
+ interface Warning {
139
+ code: WarningCode;
140
+ message: string;
141
+ details?: Record<string, unknown>;
142
+ }
143
+ type WarningHandler = (warning: Warning) => void;
144
+ /** Печатает предупреждение в `console.warn` — поведение по умолчанию. */
145
+ declare const consoleWarningHandler: WarningHandler;
146
+
147
+ /** Базовый адрес API Метрики. */
148
+ declare const DEFAULT_BASE_URL = "https://api-metrika.yandex.net";
149
+ /** Значение параметра запроса: массивы сериализуются через запятую, как требует API. */
150
+ type QueryValue = string | number | boolean | readonly (string | number)[] | undefined;
151
+ interface MetrikaClientOptions {
152
+ /** OAuth-токен Яндекса. Передаётся в заголовке `Authorization: OAuth <token>`. */
153
+ token: string;
154
+ /** Базовый URL. Переопределяется в тестах. */
155
+ baseUrl?: string;
156
+ /** Настройки лимитера или готовый лимитер (чтобы делить квоту между клиентами). */
157
+ rateLimit?: RateLimitOptions | RateLimiter;
158
+ /** Подменяемый `fetch` — для тестов и прокси. */
159
+ fetch?: typeof globalThis.fetch;
160
+ /** Сколько раз повторять запрос при 429 и 5xx. По умолчанию 3. */
161
+ maxRetries?: number;
162
+ /** Верхняя граница паузы перед повтором. По умолчанию 30 секунд. */
163
+ maxRetryDelayMs?: number;
164
+ /** Таймаут одного запроса. По умолчанию 60 секунд. */
165
+ timeoutMs?: number;
166
+ /** Язык расшифровок и значений фильтров. По умолчанию `ru`. */
167
+ lang?: 'ru' | 'en';
168
+ /** Куда отдавать предупреждения. По умолчанию `console.warn`. */
169
+ onWarning?: WarningHandler;
170
+ }
171
+ interface RequestOptions {
172
+ /** Путь без базового URL, например `/stat/v1/data`. */
173
+ path: string;
174
+ query?: Record<string, QueryValue>;
175
+ /** Группа квот: у отчётов отдельный пятиминутный лимит. */
176
+ scope: QuotaScope;
177
+ signal?: AbortSignal;
178
+ }
179
+ declare function buildUrl(baseUrl: string, path: string, query?: Record<string, QueryValue>): string;
180
+ /** Низкоуровневый клиент API Метрики. */
181
+ declare class MetrikaHttpClient {
182
+ readonly lang: 'ru' | 'en';
183
+ readonly warn: WarningHandler;
184
+ readonly limiter: RateLimiter;
185
+ private readonly token;
186
+ private readonly baseUrl;
187
+ private readonly fetchImpl;
188
+ private readonly maxRetries;
189
+ private readonly maxRetryDelayMs;
190
+ private readonly timeoutMs;
191
+ constructor(options: MetrikaClientOptions);
192
+ /** Выполняет GET-запрос и разбирает JSON-ответ. */
193
+ get<T>(options: RequestOptions): Promise<T>;
194
+ /**
195
+ * Пауза перед повтором. `undefined` — ждать пришлось бы дольше `maxRetryDelayMs`,
196
+ * повтор бессмыслен и ошибку надо отдать вызывающему коду.
197
+ */
198
+ private retryDelay;
199
+ private send;
200
+ }
201
+
202
+ /**
203
+ * API управления: счётчики и клиенты Яндекс Директа.
204
+ *
205
+ * Отсюда берутся две вещи, без которых не построить отчёт по ключевым словам:
206
+ * идентификатор счётчика (по адресу сайта) и логины клиентов Директа
207
+ * для параметра `direct_client_logins`.
208
+ */
209
+
210
+ /** Клиент Яндекс Директа, доступный счётчику. */
211
+ interface DirectClient {
212
+ id: number;
213
+ name?: string;
214
+ /** Логин главного представителя — то, что передаётся в `direct_client_logins`. */
215
+ chief_login: string;
216
+ }
217
+ /** Счётчик Метрики в плоском виде: адрес сайта поднят из вложенного `site2`. */
218
+ interface CounterBrief {
219
+ id: number;
220
+ name: string;
221
+ /** Адрес сайта. В ответе API лежит в `site2.site`. */
222
+ site: string;
223
+ /** Дополнительные адреса (зеркала). */
224
+ mirrors: string[];
225
+ status?: string;
226
+ /** Уровень доступа: `own`, `view`, `edit`. */
227
+ permission?: string;
228
+ ownerLogin?: string;
229
+ }
230
+ /** Уровень доступа к счётчику. */
231
+ type CounterPermission = 'own' | 'view' | 'edit';
232
+ interface GetCountersOptions {
233
+ /**
234
+ * Фильтр по подстроке: идентификатор, название, адрес сайта или зеркало.
235
+ * Идентификатор указывается целиком.
236
+ */
237
+ searchString?: string;
238
+ /** Ограничить уровнем доступа. */
239
+ permission?: CounterPermission[];
240
+ /** Счётчиков за запрос. Максимум 10 000, по умолчанию 1000. */
241
+ perPage?: number;
242
+ /** Номер первого счётчика в выдаче, начиная с 1. */
243
+ offset?: number;
244
+ signal?: AbortSignal;
245
+ }
246
+ /** Счётчик по адресу сайта не найден или найден не один. */
247
+ declare class CounterLookupError extends Error {
248
+ readonly candidates: CounterBrief[];
249
+ constructor(message: string, candidates: CounterBrief[]);
250
+ }
251
+ declare class ManagementApi {
252
+ private readonly http;
253
+ constructor(http: MetrikaHttpClient);
254
+ /** Счётчики, доступные владельцу токена. */
255
+ getCounters(options?: GetCountersOptions): Promise<CounterBrief[]>;
256
+ /**
257
+ * Находит единственный счётчик по адресу сайта.
258
+ * Бросает `CounterLookupError` со списком кандидатов, если совпадений нет или их несколько:
259
+ * запускать выгрузку по наугад выбранному счётчику хуже, чем остановиться.
260
+ */
261
+ findCounterBySite(site: string, signal?: AbortSignal): Promise<CounterBrief>;
262
+ /** Клиенты Директа, доступные указанным счётчикам. */
263
+ getDirectClients(counterIds: number | number[], signal?: AbortSignal): Promise<DirectClient[]>;
264
+ /** Логины для параметра `direct_client_logins`. */
265
+ getDirectClientLogins(counterIds: number | number[], signal?: AbortSignal): Promise<string[]>;
266
+ }
267
+
268
+ /** Версия контракта: первые 12 символов sha256 документации, по которой собран реестр. */
269
+ declare const contractVersion = "5695d8903f6d";
270
+ /** Полный sha256 документации-источника. */
271
+ declare const contractSourceSha256 = "5695d8903f6d252cdd95f058ed3b5984815fe96a215bbd6c23db3e349d4eb784";
272
+ /** Когда снапшот был разобран. */
273
+ declare const contractParsedAt = "2026-09-05T13:29:26.759Z";
274
+ /** Все известные группировки (684). */
275
+ declare const DIMENSION_IDS: ReadonlySet<string>;
276
+ /** Все известные метрики (538). */
277
+ declare const METRIC_IDS: ReadonlySet<string>;
278
+ /** Все известные шаблоны отчётов (93). */
279
+ declare const PRESET_IDS: ReadonlySet<string>;
280
+
281
+ /**
282
+ * Реестр известных группировок, метрик и шаблонов — извлечён из документации Метрики.
283
+ *
284
+ * Используется для валидации запросов до отправки: неизвестное имя ловится локально,
285
+ * а не превращается в `400 invalid_parameter` после расхода квоты.
286
+ */
287
+
288
+ /** Пространства имён API отчётов: визиты, просмотры, реклама, расходы, события, загрузки, параметры. */
289
+ type Namespace = 's' | 'pv' | 'ad' | 'ev' | 'ep' | 'dl' | 'up';
290
+ /** Возвращает пространство имён идентификатора: `ym:s:visits` → `s`. */
291
+ declare function namespaceOf(id: string): string | undefined;
292
+ /**
293
+ * Приводит конкретный идентификатор к форме из документации, заменяя подставленные
294
+ * значения параметров обратно на плейсхолдеры: `ym:s:lastSearchPhrase` → `ym:s:<attribution>SearchPhrase`.
295
+ */
296
+ declare const ATTRIBUTIONS: readonly ["cross_device_first", "cross_device_last_significant", "last_significant", "last_yandex_direct_click", "automatic", "first", "last"];
297
+ /** Модели атрибуции, поддерживаемые API отчётов. */
298
+ type Attribution = (typeof ATTRIBUTIONS)[number];
299
+ /**
300
+ * Модели, которые с 25 июня 2026 года схлопываются в ближайшие аналоги.
301
+ * Библиотека их принимает, но предупреждает.
302
+ */
303
+ declare const DEPRECATED_ATTRIBUTIONS: Readonly<Record<string, Attribution>>;
304
+ /** Валюты, доступные в параметре `<currency>`. */
305
+ type Currency = 'RUB' | 'USD' | 'EUR' | 'YND';
306
+ /** Известна ли группировка (идентификатор в форме документации, с плейсхолдерами). */
307
+ declare function hasDimension(id: string): boolean;
308
+ /** Известна ли метрика (идентификатор в форме документации, с плейсхолдерами). */
309
+ declare function hasMetric(id: string): boolean;
310
+ /** Известен ли шаблон отчёта. */
311
+ declare function hasPreset(id: string): boolean;
312
+
313
+ /** Типы API отчётов (`/stat/v1/data`, `/stat/v1/data/bytime`). */
314
+
315
+ /**
316
+ * Значение группировки. Для группировок с расшифровкой приходит `{id, name}`,
317
+ * для остальных — только `name`; география добавляет `iso_name` и иконки.
318
+ */
319
+ interface DimensionValue {
320
+ id?: string | null;
321
+ name?: string | null;
322
+ icon_id?: string | null;
323
+ icon_type?: string | null;
324
+ iso_name?: string | null;
325
+ [key: string]: unknown;
326
+ }
327
+ /** Строка отчёта: значения группировок и соответствующие им метрики. */
328
+ interface StatRow {
329
+ dimensions: DimensionValue[];
330
+ metrics: (number | null)[];
331
+ }
332
+ /** Ответ `/stat/v1/data`. */
333
+ interface StatDataResponse {
334
+ query: {
335
+ ids: number[];
336
+ dimensions: string[];
337
+ metrics: string[];
338
+ sort?: string[];
339
+ date1: string;
340
+ date2: string;
341
+ filters?: string;
342
+ limit: number;
343
+ offset: number;
344
+ [key: string]: unknown;
345
+ };
346
+ data: StatRow[];
347
+ total_rows: number;
348
+ total_rows_rounded?: boolean;
349
+ sampled: boolean;
350
+ sample_share?: number;
351
+ sample_size?: number;
352
+ sample_space?: number;
353
+ /** `true` — часть строк скрыта порогом приватности (выборка меньше 10 посетителей). */
354
+ contains_sensitive_data?: boolean;
355
+ /** Задержка данных в секундах. */
356
+ data_lag?: number;
357
+ totals?: (number | null)[];
358
+ min?: (number | null)[];
359
+ max?: (number | null)[];
360
+ }
361
+ /** Строка отчёта по времени: серия значений по точкам временной шкалы. */
362
+ interface BytimeRow {
363
+ dimensions: DimensionValue[];
364
+ metrics: (number | null)[][];
365
+ }
366
+ /** Ответ `/stat/v1/data/bytime`. */
367
+ interface BytimeResponse extends Omit<StatDataResponse, 'data'> {
368
+ data: BytimeRow[];
369
+ /** Метки времени точек графика. */
370
+ time_intervals: [string, string][];
371
+ }
372
+ /** Группировка по времени для `/stat/v1/data/bytime`. */
373
+ type TimeGroup = 'all' | 'auto' | 'minute' | 'dekaminute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
374
+ /** Управление семплированием. */
375
+ type Accuracy = 'low' | 'medium' | 'high' | 'full' | number;
376
+ /** Параметры запроса к API отчётов. */
377
+ interface StatQuery {
378
+ /** Идентификаторы счётчиков. */
379
+ ids: number | number[];
380
+ metrics: string[];
381
+ dimensions?: string[];
382
+ /** Шаблон отчёта. Явные `metrics`/`dimensions` имеют приоритет над шаблоном. */
383
+ preset?: string;
384
+ /** Дата начала: `YYYY-MM-DD`, `today`, `yesterday`, `NdaysAgo`. */
385
+ date1?: string;
386
+ date2?: string;
387
+ filters?: string;
388
+ sort?: string[];
389
+ /** По умолчанию `full` — иначе редкие фразы выпадают из выборки. */
390
+ accuracy?: Accuracy;
391
+ /** Разрешить API поднять `accuracy` до рекомендованного значения. */
392
+ proposedAccuracy?: boolean;
393
+ limit?: number;
394
+ offset?: number;
395
+ /** Модель атрибуции для группировок с `<attribution>`. */
396
+ attribution?: Attribution;
397
+ /** Валюта для метрик с `<currency>`. */
398
+ currency?: Currency;
399
+ /** Идентификатор цели для метрик с `<goal_id>`. */
400
+ goalId?: number;
401
+ /** Логины клиентов Директа — обязательны для отчётов в пространстве `ym:ad:`. */
402
+ directClientLogins?: string[];
403
+ /** Включить строки с неопределённым значением первой группировки. */
404
+ includeUndefined?: boolean;
405
+ timezone?: string;
406
+ lang?: 'ru' | 'en';
407
+ }
408
+ /** Диагностика выгрузки: качество данных и предупреждения. */
409
+ interface ReportMeta {
410
+ /** Версия контракта, по которой собран запрос. */
411
+ contractVersion: string;
412
+ sampled: boolean;
413
+ sampleShare?: number;
414
+ sampleSize?: number;
415
+ sampleSpace?: number;
416
+ /** Часть строк скрыта порогом приватности. */
417
+ containsSensitiveData: boolean;
418
+ dataLagSeconds?: number;
419
+ totalRows: number;
420
+ /** Сколько строк реально выгружено. */
421
+ fetchedRows: number;
422
+ requests: number;
423
+ warnings: Warning[];
424
+ }
425
+ /** Результат выгрузки: строки плюс диагностика. */
426
+ interface Report<TRow> {
427
+ rows: TRow[];
428
+ meta: ReportMeta;
429
+ }
430
+
431
+ /**
432
+ * API отчётов: `/stat/v1/data` (таблица) и `/stat/v1/data/bytime` (по времени).
433
+ */
434
+
435
+ interface ReportsApiOptions {
436
+ /** Не бросать исключение на группировку, которой нет в снапшоте, а предупреждать. */
437
+ allowUnknownFields?: boolean;
438
+ }
439
+ interface FetchAllOptions {
440
+ /** Верхняя граница выгрузки. Без неё выгружаются все `total_rows`. */
441
+ maxRows?: number;
442
+ /** Строк за запрос. По умолчанию 100 000 — максимум API. */
443
+ pageSize?: number;
444
+ signal?: AbortSignal;
445
+ }
446
+ interface BytimeQuery extends StatQuery {
447
+ /** Разбиение шкалы времени. По умолчанию `day`. */
448
+ group?: TimeGroup;
449
+ /** Сколько строк строить, если не заданы `rowIds`. Максимум 30. */
450
+ topKeys?: number;
451
+ /** Явный выбор строк по ключам группировок. */
452
+ rowIds?: string[][];
453
+ }
454
+ /** Преобразует запрос библиотеки в query-параметры API. */
455
+ declare function toQueryParams(query: StatQuery, lang: 'ru' | 'en'): Record<string, QueryValue>;
456
+ /** Собирает предупреждения о качестве данных из ответа API. */
457
+ declare function inspectResponse(response: StatDataResponse): Warning[];
458
+ /** Типизированный доступ к API отчётов. */
459
+ declare class ReportsApi {
460
+ private readonly http;
461
+ private readonly options;
462
+ constructor(http: MetrikaHttpClient, options?: ReportsApiOptions);
463
+ /** Одна страница отчёта. Сырой ответ API без постобработки. */
464
+ fetchPage(query: StatQuery, signal?: AbortSignal): Promise<StatDataResponse>;
465
+ /**
466
+ * Выгружает отчёт целиком, постранично по `total_rows`.
467
+ * Период по умолчанию — 30 дней, заканчивающихся на T-3 (данные визитов дозаполняются ~3 дня).
468
+ */
469
+ fetchAll(query: StatQuery, options?: FetchAllOptions): Promise<Report<StatRow>>;
470
+ /** Ленивая постраничная выгрузка — когда весь отчёт не нужно держать в памяти. */
471
+ stream(query: StatQuery, options?: FetchAllOptions): AsyncGenerator<StatRow>;
472
+ /** Отчёт с разбивкой по времени — для динамики фраз. */
473
+ bytime(query: BytimeQuery, signal?: AbortSignal): Promise<BytimeResponse>;
474
+ }
475
+
476
+ /**
477
+ * Общее для рецептов выгрузки ключевых слов: идентификаторы группировок и метрик,
478
+ * сборка фильтров и безопасное чтение ячеек ответа.
479
+ */
480
+
481
+ /** Группировки, на которых держатся рецепты. Форма — как в документации, с плейсхолдерами. */
482
+ declare const DIM: {
483
+ readonly searchPhrase: "ym:s:<attribution>SearchPhrase";
484
+ readonly searchEngineRoot: "ym:s:<attribution>SearchEngineRoot";
485
+ readonly trafficSource: "ym:s:<attribution>TrafficSource";
486
+ readonly isRobot: "ym:s:isRobot";
487
+ readonly startUrl: "ym:s:startURL";
488
+ readonly visitDirectSearchPhrase: "ym:s:<attribution>DirectSearchPhrase";
489
+ readonly visitDirectPhraseOrCond: "ym:s:<attribution>DirectPhraseOrCond";
490
+ readonly adDirectSearchPhrase: "ym:ad:<attribution>DirectSearchPhrase";
491
+ readonly adDirectPhraseOrCond: "ym:ad:<attribution>DirectPhraseOrCond";
492
+ readonly adDirectOrder: "ym:ad:<attribution>DirectOrder";
493
+ readonly adDirectConditionType: "ym:ad:<attribution>DirectConditionType";
494
+ };
495
+ /** Метрики, на которых держатся рецепты. */
496
+ declare const METRIC: {
497
+ readonly visits: "ym:s:visits";
498
+ readonly users: "ym:s:users";
499
+ readonly bounceRate: "ym:s:bounceRate";
500
+ readonly pageDepth: "ym:s:pageDepth";
501
+ readonly avgVisitDuration: "ym:s:avgVisitDurationSeconds";
502
+ readonly anyGoalConversionRate: "ym:s:anyGoalConversionRate";
503
+ readonly adClicks: "ym:ad:clicks";
504
+ readonly adVisits: "ym:ad:visits";
505
+ readonly adUsers: "ym:ad:users";
506
+ readonly adBounceRate: "ym:ad:bounceRate";
507
+ readonly adCost: "ym:ad:<currency>ConvertedAdCost";
508
+ readonly adCostPerVisit: "ym:ad:<currency>ConvertedAdCostPerVisit";
509
+ };
510
+ /** Общие параметры всех рецептов. */
511
+ interface KeywordQueryOptions {
512
+ /** Счётчик или счётчики Метрики. */
513
+ counterId: number | number[];
514
+ /** Начало периода. По умолчанию 30 дней, заканчивающихся на T-3. */
515
+ date1?: string;
516
+ date2?: string;
517
+ /** Модель атрибуции. По умолчанию `last`. */
518
+ attribution?: Attribution;
519
+ /** Дополнительный фильтр сегментации — приклеивается к фильтру рецепта через `AND`. */
520
+ filters?: string;
521
+ /** Верхняя граница выгрузки. Без неё выгружается весь отчёт. */
522
+ maxRows?: number;
523
+ signal?: AbortSignal;
524
+ }
525
+ /** Склеивает условия фильтра через `AND`, отбрасывая пустые. */
526
+ declare function andFilters(...parts: (string | undefined)[]): string | undefined;
527
+ /**
528
+ * Нормализует поисковую фразу для склейки источников: обрезает края,
529
+ * схлопывает пробелы, приводит к нижнему регистру и унифицирует `ё`.
530
+ * Метрика отдаёт одну и ту же фразу с разным регистром из органики и Директа.
531
+ */
532
+ declare function normalizePhrase(phrase: string): string;
533
+
534
+ /**
535
+ * Рецепт C — Яндекс Директ: реальные запросы, клики и расходы.
536
+ *
537
+ * Работает в пространстве `ym:ad:`, поэтому требует `direct_client_logins` —
538
+ * логины клиентов Директа, к кампаниям которых есть доступ у владельца счётчика.
539
+ * Эквивалент шаблона `preset=sources_direct_clicks`, дополненный метрикой `ym:ad:clicks`.
540
+ */
541
+
542
+ /** Строка отчёта по расходам Директа в разрезе запроса и ключевого слова. */
543
+ interface DirectCostRow {
544
+ /** Реальный поисковый запрос, по которому показалось объявление. */
545
+ query: string;
546
+ /** Условие показа: ключевое слово или условие ретаргетинга. */
547
+ keyword: string;
548
+ /** Тип условия показа — позволяет отделить ключевики от ретаргетинга. */
549
+ conditionType?: string;
550
+ campaignId?: string;
551
+ campaignName: string;
552
+ /** Клики по рекламе. */
553
+ clicks: number;
554
+ visits: number;
555
+ users: number;
556
+ /** Расходы в валюте отчёта. */
557
+ cost: number;
558
+ /** Средняя стоимость визита. */
559
+ costPerVisit: number;
560
+ bounceRate: number;
561
+ }
562
+ interface DirectCostOptions extends KeywordQueryOptions {
563
+ /**
564
+ * Логины клиентов Директа. Обязательны: без них API отчётов не строит `ym:ad:`.
565
+ * Получить: `ManagementApi.getDirectClientLogins(counterId)`.
566
+ */
567
+ directClientLogins: string[];
568
+ /** Валюта расходов. По умолчанию — валюта счётчика. */
569
+ currency?: Currency;
570
+ /**
571
+ * Оставить только указанные типы условия показа — так отсекаются условия ретаргетинга.
572
+ * Документация не перечисляет допустимые значения, поэтому список передаётся явно:
573
+ * сначала выгрузите отчёт без фильтра и посмотрите, какие `conditionType` встречаются.
574
+ */
575
+ conditionTypes?: string[];
576
+ }
577
+ /** Выгружает запросы Директа с кликами и расходами по каждому ключевому слову. */
578
+ declare function getDirectSearchPhraseCost(reports: ReportsApi, options: DirectCostOptions): Promise<Report<DirectCostRow>>;
579
+
580
+ /**
581
+ * Рецепт D — ключевые слова Директа по визитам, без доступа к кампаниям.
582
+ *
583
+ * Работает в пространстве `ym:s:`, поэтому не требует `direct_client_logins`.
584
+ * Отдаёт слова и запросы с качеством визита и конверсией, но без кликов и расходов —
585
+ * их можно получить только рецептом C.
586
+ * Эквивалент шаблона `preset=sources_direct_summary`.
587
+ */
588
+
589
+ /** Строка отчёта по ключевым словам Директа в разрезе визитов. */
590
+ interface DirectVisitRow {
591
+ /** Условие показа: ключевое слово или условие ретаргетинга. */
592
+ keyword: string;
593
+ /** Реальный поисковый запрос, по которому показалось объявление. */
594
+ query: string;
595
+ visits: number;
596
+ users: number;
597
+ bounceRate: number;
598
+ /** Конверсия по любой цели, %. */
599
+ anyGoalConversionRate: number;
600
+ }
601
+ /** Выгружает ключевые слова и запросы Директа без доступа к рекламным кампаниям. */
602
+ declare function getDirectKeywordsByVisits(reports: ReportsApi, options: KeywordQueryOptions & {
603
+ excludeRobots?: boolean;
604
+ }): Promise<Report<DirectVisitRow>>;
605
+
606
+ /**
607
+ * Рецепт A — поисковые фразы органики: по каким словам сайт находят в поиске.
608
+ *
609
+ * Эквивалент шаблона `preset=sources_search_phrases`, но с отсечкой роботов
610
+ * и `accuracy=full`, иначе длинный хвост фраз выпадает из выборки.
611
+ */
612
+
613
+ /** Строка отчёта по органическим поисковым фразам. */
614
+ interface OrganicPhraseRow {
615
+ /** Поисковая фраза как её отдал API. */
616
+ phrase: string;
617
+ /** Название поисковой системы (Яндекс, Google, …). */
618
+ searchEngine: string;
619
+ /** Идентификатор поисковой системы. */
620
+ searchEngineId?: string;
621
+ visits: number;
622
+ users: number;
623
+ /** Доля отказов, %. */
624
+ bounceRate: number;
625
+ /** Средняя глубина просмотра. */
626
+ pageDepth: number;
627
+ /** Среднее время на сайте, секунды. */
628
+ avgVisitDurationSeconds: number;
629
+ }
630
+ interface OrganicPhrasesOptions extends KeywordQueryOptions {
631
+ /** Исключить визиты роботов. По умолчанию `true`. */
632
+ excludeRobots?: boolean;
633
+ /** Ограничить конкретными поисковыми системами, например `['yandex']`. */
634
+ searchEngines?: string[];
635
+ }
636
+ /** Фильтр рецепта: только переходы из поисковых систем, по умолчанию без роботов. */
637
+ declare function organicFilters(options: OrganicPhrasesOptions): string | undefined;
638
+ /** Выгружает поисковые фразы органики со статистикой качества визита. */
639
+ declare function getOrganicSearchPhrases(reports: ReportsApi, options: OrganicPhrasesOptions): Promise<Report<OrganicPhraseRow>>;
640
+
641
+ /**
642
+ * Рецепт B — фраза × посадочная страница.
643
+ *
644
+ * Связывает ключевое слово с конкретным материалом сайта: основа для того,
645
+ * чтобы понять, какой контент уже отвечает на запрос, а какой ещё нужно написать.
646
+ */
647
+
648
+ /** Строка отчёта «фраза → страница входа». */
649
+ interface PhraseLandingRow {
650
+ phrase: string;
651
+ /** Адрес страницы входа. */
652
+ url: string;
653
+ visits: number;
654
+ users: number;
655
+ bounceRate: number;
656
+ avgVisitDurationSeconds: number;
657
+ }
658
+ /** Выгружает связку «поисковая фраза → посадочная страница» для органики. */
659
+ declare function getPhraseLandingMap(reports: ReportsApi, options: OrganicPhrasesOptions): Promise<Report<PhraseLandingRow>>;
660
+
661
+ /**
662
+ * Рецепт E — динамика фраз во времени.
663
+ *
664
+ * Отвечает на вопрос «какие слова сейчас растут»: именно растущие фразы стоит брать
665
+ * в работу, а не те, что просто набрали много визитов за весь период.
666
+ * Ограничение API: не более 30 строк на график (`top_keys`).
667
+ */
668
+
669
+ /** Максимум строк, который API отдаёт для отчёта по времени. */
670
+ declare const MAX_TIMELINE_ROWS = 30;
671
+ /** Точка временного ряда. */
672
+ interface TimelinePoint {
673
+ /** Начало интервала. */
674
+ from: string;
675
+ /** Конец интервала. */
676
+ to: string;
677
+ visits: number;
678
+ }
679
+ /** Временной ряд одной фразы. */
680
+ interface PhraseTimeline {
681
+ phrase: string;
682
+ points: TimelinePoint[];
683
+ /** Суммарные визиты за период. */
684
+ totalVisits: number;
685
+ /**
686
+ * Отношение визитов второй половины периода к первой.
687
+ * Больше 1 — фраза растёт, меньше 1 — затухает; `null`, если первая половина пуста.
688
+ */
689
+ trend: number | null;
690
+ }
691
+ interface PhraseTimelineOptions extends OrganicPhrasesOptions {
692
+ /** Разбиение шкалы. По умолчанию `day`. */
693
+ group?: TimeGroup;
694
+ /** Сколько top-фраз строить. По умолчанию 10, максимум 30. */
695
+ topPhrases?: number;
696
+ /** Явный список фраз вместо топа. */
697
+ phrases?: string[];
698
+ }
699
+ /** Выгружает динамику визитов по органическим поисковым фразам. */
700
+ declare function getPhraseTimeline(reports: ReportsApi, options: PhraseTimelineOptions): Promise<PhraseTimeline[]>;
701
+
702
+ /**
703
+ * Метки качества данных.
704
+ *
705
+ * Метрика скрывает конфиденциальные данные — в том числе поисковые фразы — если
706
+ * в выборке меньше 10 посетителей. Это ровно тот диапазон, где живёт длинный хвост
707
+ * запросов, поэтому строку рядом с порогом нельзя молча считать полной.
708
+ */
709
+
710
+ /** Порог раскрытия конфиденциальных данных в отчётах Метрики. */
711
+ declare const PRIVACY_THRESHOLD_USERS = 10;
712
+ /** Оговорки, с которыми нужно читать конкретную запись реестра. */
713
+ interface KeywordQuality {
714
+ /** Отчёт построен по неполной выборке. */
715
+ sampled: boolean;
716
+ /** В отчёте могли быть скрыты строки с малой выборкой. */
717
+ sensitiveDataHidden: boolean;
718
+ /**
719
+ * Суммарно посетителей меньше порога раскрытия: рядом с этой записью в отчёте
720
+ * почти наверняка не хватает соседних, отсечённых порогом.
721
+ */
722
+ belowPrivacyThreshold: boolean;
723
+ }
724
+ /** Диагностика склеенного реестра. */
725
+ interface MergedMeta {
726
+ contractVersion: string;
727
+ /** Хотя бы один из отчётов был семплирован. */
728
+ sampled: boolean;
729
+ /** Минимальная доля выборки среди отчётов — худший случай. */
730
+ minSampleShare?: number;
731
+ containsSensitiveData: boolean;
732
+ /** Сколько записей попало под порог раскрытия. */
733
+ belowPrivacyThreshold: number;
734
+ /** Суммарно запросов к API. */
735
+ requests: number;
736
+ warnings: Warning[];
737
+ /** Из каких отчётов собран реестр. */
738
+ sources: string[];
739
+ }
740
+ /**
741
+ * Оговорки уровня отчёта. `belowPrivacyThreshold` здесь всегда `false`:
742
+ * он зависит от суммарного числа посетителей ключевого слова и проставляется
743
+ * в конце склейки — см. `isBelowPrivacyThreshold`.
744
+ */
745
+ declare function qualityOf(meta: ReportMeta): KeywordQuality;
746
+ /**
747
+ * Попадает ли ключевое слово под порог раскрытия.
748
+ *
749
+ * Считать это построчно нельзя: одна фраза приходит несколькими строками —
750
+ * разный регистр написания, разные поисковые системы. Редкий вариант с четырьмя
751
+ * посетителями пометил бы всё слово, у которого суммарно их пятьсот.
752
+ * Поэтому флаг считается один раз по итоговой сумме.
753
+ */
754
+ declare function isBelowPrivacyThreshold(users: number): boolean;
755
+ /** Объединяет метки уровня отчёта: запись видна в нескольких выгрузках. */
756
+ declare function mergeQuality(a: KeywordQuality, b: KeywordQuality): KeywordQuality;
757
+ /** Сводит метаданные нескольких отчётов в одну диагностику. */
758
+ declare function mergeMeta(entries: {
759
+ source: string;
760
+ meta: ReportMeta;
761
+ }[], belowPrivacyThreshold: number): MergedMeta;
762
+
763
+ /**
764
+ * Слой нормализации: сводит выгрузки органики и Директа в единый реестр ключевых слов.
765
+ *
766
+ * Ключ склейки — нормализованная фраза реального пользовательского запроса
767
+ * (`SearchPhrase` из органики, `DirectSearchPhrase` из Директа). Купленные ключевые
768
+ * слова Директа (`DirectPhraseOrCond`) — другой уровень агрегации, поэтому они не
769
+ * смешиваются с запросами, а складываются в `direct.keywords` и в отдельную сводку
770
+ * `aggregateDirectKeywords`.
771
+ */
772
+
773
+ /** Откуда в реестре взялась фраза. */
774
+ type KeywordSource = 'organic' | 'direct_query';
775
+ /** Показатели фразы в органическом поиске. */
776
+ interface OrganicStats {
777
+ visits: number;
778
+ users: number;
779
+ bounceRate: number;
780
+ pageDepth: number;
781
+ avgVisitDurationSeconds: number;
782
+ /** Поисковые системы, из которых приходили по этой фразе. */
783
+ searchEngines: string[];
784
+ }
785
+ /** Показатели фразы в Яндекс Директе. */
786
+ interface DirectStats {
787
+ clicks: number;
788
+ visits: number;
789
+ users: number;
790
+ cost: number;
791
+ costPerVisit: number;
792
+ bounceRate: number;
793
+ /** Купленные ключевые слова (условия показа), по которым показывалось объявление. */
794
+ keywords: string[];
795
+ campaigns: string[];
796
+ /** Конверсия по любой цели, если данные пришли из рецепта по визитам. */
797
+ anyGoalConversionRate?: number;
798
+ }
799
+ /** Посадочная страница, на которую приходили по фразе. */
800
+ interface KeywordLanding {
801
+ url: string;
802
+ visits: number;
803
+ }
804
+ /** Запись реестра ключевых слов. */
805
+ interface Keyword {
806
+ /** Нормализованная фраза — ключ склейки. */
807
+ phrase: string;
808
+ /** Написание, как его отдал API (первое встреченное). */
809
+ displayPhrase: string;
810
+ sources: KeywordSource[];
811
+ organic?: OrganicStats;
812
+ direct?: DirectStats;
813
+ landings: KeywordLanding[];
814
+ /** Визиты из всех источников — основная величина для сортировки. */
815
+ totalVisits: number;
816
+ /** Посетители из всех источников. По ним считается порог раскрытия. */
817
+ totalUsers: number;
818
+ quality: KeywordQuality;
819
+ }
820
+ /** Реестр ключевых слов и диагностика его сборки. */
821
+ interface KeywordRegistry {
822
+ keywords: Keyword[];
823
+ meta: MergedMeta;
824
+ }
825
+ /** Выгрузки, из которых собирается реестр. Все части необязательны. */
826
+ interface MergeInput {
827
+ organic?: Report<OrganicPhraseRow>;
828
+ landings?: Report<PhraseLandingRow>;
829
+ directCost?: Report<DirectCostRow>;
830
+ directVisits?: Report<DirectVisitRow>;
831
+ }
832
+ /** Сводка по купленному ключевому слову Директа. */
833
+ interface DirectKeywordSummary {
834
+ keyword: string;
835
+ clicks: number;
836
+ visits: number;
837
+ users: number;
838
+ cost: number;
839
+ /** Реальные запросы, приведшие к показу по этому слову. */
840
+ queries: string[];
841
+ campaigns: string[];
842
+ }
843
+ /** Склеивает выгрузки в единый реестр, отсортированный по суммарным визитам. */
844
+ declare function mergeKeywords(input: MergeInput): KeywordRegistry;
845
+ /** Сводит расходы Директа по купленным ключевым словам, а не по запросам. */
846
+ declare function aggregateDirectKeywords(report: Report<DirectCostRow>): DirectKeywordSummary[];
847
+
848
+ /**
849
+ * Фасад библиотеки: клиент, отчёты и рецепты выгрузки ключевых слов в одном объекте.
850
+ */
851
+
852
+ type MetrikaOptions = MetrikaClientOptions & ReportsApiOptions;
853
+ /** Что именно собирать в реестр ключевых слов. */
854
+ interface KeywordRegistryOptions extends OrganicPhrasesOptions {
855
+ /** Добавить связку «фраза → посадочная страница». По умолчанию `true`. */
856
+ withLandings?: boolean;
857
+ /**
858
+ * Добавить клики и расходы Директа. По умолчанию `true`.
859
+ * Логины клиентов подставляются автоматически; если доступа к Директу нет,
860
+ * блок пропускается с предупреждением.
861
+ */
862
+ withDirect?: boolean;
863
+ /** Готовые логины клиентов Директа — чтобы не тратить запрос на их получение. */
864
+ directClientLogins?: string[];
865
+ }
866
+ /** Точка входа: `new YandexMetrika({ token })`. */
867
+ declare class YandexMetrika {
868
+ readonly http: MetrikaHttpClient;
869
+ readonly reports: ReportsApi;
870
+ readonly management: ManagementApi;
871
+ constructor(options: MetrikaOptions);
872
+ /** Версия контракта, по которой собрана библиотека. */
873
+ contract(): {
874
+ version: string;
875
+ sourceSha256: string;
876
+ parsedAt: string;
877
+ };
878
+ /** Рецепт A: поисковые фразы органики. */
879
+ getOrganicSearchPhrases(options: OrganicPhrasesOptions): Promise<Report<OrganicPhraseRow>>;
880
+ /** Рецепт B: фраза × посадочная страница. */
881
+ getPhraseLandingMap(options: OrganicPhrasesOptions): Promise<Report<PhraseLandingRow>>;
882
+ /**
883
+ * Рецепт C: запросы Директа с кликами и расходами.
884
+ * Если `directClientLogins` не передан, логины запрашиваются автоматически.
885
+ */
886
+ getDirectSearchPhraseCost(options: Omit<DirectCostOptions, 'directClientLogins'> & {
887
+ directClientLogins?: string[];
888
+ }): Promise<Report<DirectCostRow>>;
889
+ /** Рецепт D: ключевые слова Директа по визитам, без доступа к кампаниям. */
890
+ getDirectKeywordsByVisits(options: KeywordQueryOptions & {
891
+ excludeRobots?: boolean;
892
+ }): Promise<Report<DirectVisitRow>>;
893
+ /** Рецепт E: динамика фраз во времени. */
894
+ getPhraseTimeline(options: PhraseTimelineOptions): Promise<PhraseTimeline[]>;
895
+ /**
896
+ * Сквозной сценарий: выгружает органику, посадочные страницы и Директ,
897
+ * склеивает в единый реестр ключевых слов.
898
+ */
899
+ buildKeywordRegistry(options: KeywordRegistryOptions): Promise<KeywordRegistry>;
900
+ }
901
+
902
+ /** Документированные лимиты запроса к API отчётов. */
903
+ declare const LIMITS: {
904
+ readonly maxDimensions: 10;
905
+ readonly maxMetrics: 20;
906
+ readonly maxRowsPerRequest: 100000;
907
+ readonly maxFilterLength: 10000;
908
+ readonly maxFilterValues: 100;
909
+ };
910
+ /**
911
+ * Приводит идентификатор к форме документации, подставляя обратно плейсхолдеры:
912
+ * `ym:s:lastSearchPhrase` → `ym:s:<attribution>SearchPhrase`,
913
+ * `ym:ad:RUBConvertedAdCost` → `ym:ad:<currency>ConvertedAdCost`,
914
+ * `ym:s:goal123visits` → `ym:s:goal<goal_id>visits`.
915
+ */
916
+ declare function toContractForm(id: string): string;
917
+ interface ValidationResult {
918
+ warnings: Warning[];
919
+ }
920
+ /** Проверяет запрос и возвращает предупреждения; на грубых ошибках бросает исключение. */
921
+ declare function validateQuery(query: StatQuery, options?: {
922
+ allowUnknownFields?: boolean;
923
+ }): ValidationResult;
924
+
925
+ /**
926
+ * Даты отчётного периода.
927
+ *
928
+ * Визиты дозаполняются по мере поступления данных: в среднем 99 % визитов завершаются
929
+ * в течение 3 дней после начала. Поэтому окно по умолчанию заканчивается на T-3,
930
+ * иначе последние дни выглядят «просевшими» и портят сравнение периодов.
931
+ */
932
+ /** Сколько последних дней считаются недозаполненными. */
933
+ declare const SETTLED_LAG_DAYS = 3;
934
+ /** Отчётный период: значения в формате API (`YYYY-MM-DD` или `NdaysAgo`). */
935
+ interface DateRange {
936
+ date1: string;
937
+ date2: string;
938
+ }
939
+ /**
940
+ * Окно из `days` дней, заканчивающееся за `lagDays` дней до сегодня.
941
+ * `settledRange(30)` → `{ date1: '32daysAgo', date2: '3daysAgo' }`.
942
+ */
943
+ declare function settledRange(days?: number, lagDays?: number): DateRange;
944
+
945
+ /**
946
+ * Идентификаторы, на которых держатся рецепты библиотеки.
947
+ *
948
+ * `check-contract` падает, если что-то отсюда исчезло или изменилось в документации:
949
+ * это ровно тот набор, поломка которого ломает библиотеку, а не просто расширяет API.
950
+ * Записи в `<attribution>`/`<currency>`-форме — как в документации, до подстановки параметров.
951
+ */
952
+ /** Группировки, используемые рецептами. Ключ — идентификатор, значение — где он нужен. */
953
+ declare const USED_DIMENSIONS: Readonly<Record<string, string>>;
954
+ /** Метрики, используемые рецептами. */
955
+ declare const USED_METRICS: Readonly<Record<string, string>>;
956
+ /** Шаблоны, на которые библиотека ссылается в документации и тестах. */
957
+ declare const USED_PRESETS: Readonly<Record<string, string>>;
958
+
959
+ /** Типы машиночитаемого контракта API Метрики, извлекаемого из `llms-full.txt`. */
960
+ interface DimensionEntry {
961
+ /** Полный идентификатор, например `ym:s:<attribution>SearchPhrase`. */
962
+ id: string;
963
+ /** Человекочитаемое название из документации. */
964
+ title?: string;
965
+ /** Операторы фильтрации, разрешённые для этой группировки. */
966
+ operators?: string[];
967
+ /** Группировка-расшифровка, отдающая `{id, name}` вместо голого идентификатора. */
968
+ decoder?: string;
969
+ /** Минимальная дата, за которую можно построить отчёт (YYYY-MM-DD). */
970
+ since?: string;
971
+ }
972
+ interface MetricEntry {
973
+ id: string;
974
+ title?: string;
975
+ /** `int`, `double`, `percents`, `currency`, `second`, `affinity` … */
976
+ type?: string;
977
+ /** Можно ли использовать метрику в `filters`. */
978
+ filterable?: boolean;
979
+ since?: string;
980
+ }
981
+ interface PresetEntry {
982
+ id: string;
983
+ title?: string;
984
+ dimensions: string[];
985
+ metrics: string[];
986
+ }
987
+ interface Contract {
988
+ /** ISO-время разбора. */
989
+ parsedAt: string;
990
+ /** sha256 исходного документа. */
991
+ sourceSha256: string;
992
+ /** Число строк в исходном документе — грубая проверка, что скачали документ целиком. */
993
+ sourceLines: number;
994
+ dimensions: Record<string, DimensionEntry>;
995
+ metrics: Record<string, MetricEntry>;
996
+ presets: Record<string, PresetEntry>;
997
+ }
998
+
999
+ export { type Accuracy, type ApiErrorBody, type ApiErrorDetail, type Attribution, AuthError, type BytimeQuery, type BytimeResponse, type BytimeRow, type Contract, type CounterBrief, CounterLookupError, type CounterPermission, type Currency, DEFAULT_BASE_URL, DEPRECATED_ATTRIBUTIONS, DIM, DIMENSION_IDS, type DateRange, type DimensionEntry, type DimensionValue, type DirectClient, type DirectCostOptions, type DirectCostRow, type DirectKeywordSummary, type DirectStats, type DirectVisitRow, type FetchAllOptions, type GetCountersOptions, InvalidRequestError, type Keyword, type KeywordLanding, type KeywordQuality, type KeywordQueryOptions, type KeywordRegistry, type KeywordRegistryOptions, type KeywordSource, LIMITS, MAX_TIMELINE_ROWS, METRIC, METRIC_IDS, ManagementApi, type MergeInput, type MergedMeta, type MetricEntry, type MetrikaClientOptions, MetrikaError, MetrikaHttpClient, type MetrikaOptions, type Namespace, NotFoundError, type OrganicPhraseRow, type OrganicPhrasesOptions, type OrganicStats, PRESET_IDS, PRIVACY_THRESHOLD_USERS, type PhraseLandingRow, type PhraseTimeline, type PhraseTimelineOptions, type PresetEntry, type QueryValue, QuotaError, type QuotaScope, type RateLimitOptions, RateLimiter, type Report, type ReportMeta, ReportsApi, type ReportsApiOptions, type RequestOptions, RequestValidationError, SETTLED_LAG_DAYS, ServerError, type StatDataResponse, type StatQuery, type StatRow, type TimeGroup, type TimelinePoint, USED_DIMENSIONS, USED_METRICS, USED_PRESETS, type Warning, type WarningCode, type WarningHandler, YandexMetrika, aggregateDirectKeywords, andFilters, buildUrl, consoleWarningHandler, contractParsedAt, contractSourceSha256, contractVersion, getDirectKeywordsByVisits, getDirectSearchPhraseCost, getOrganicSearchPhrases, getPhraseLandingMap, getPhraseTimeline, hasDimension, hasMetric, hasPreset, inspectResponse, isBelowPrivacyThreshold, isRetryable, mergeKeywords, mergeMeta, mergeQuality, namespaceOf, normalizePhrase, organicFilters, qualityOf, settledRange, toContractForm, toMetrikaError, toQueryParams, validateQuery };