@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.
package/dist/index.js ADDED
@@ -0,0 +1,2707 @@
1
+ // src/contract/registry.generated.ts
2
+ var contractVersion = "5695d8903f6d";
3
+ var contractSourceSha256 = "5695d8903f6d252cdd95f058ed3b5984815fe96a215bbd6c23db3e349d4eb784";
4
+ var contractParsedAt = "2026-09-05T13:29:26.759Z";
5
+ var DIMENSION_IDS = /* @__PURE__ */ new Set([
6
+ "ym:ad:<attribution>Currency",
7
+ "ym:ad:<attribution>DirectBanner",
8
+ "ym:ad:<attribution>DirectBannerGroup",
9
+ "ym:ad:<attribution>DirectConditionType",
10
+ "ym:ad:<attribution>DirectOrder",
11
+ "ym:ad:<attribution>DirectPhraseOrCond",
12
+ "ym:ad:<attribution>DirectPlatform",
13
+ "ym:ad:<attribution>DirectPlatformType",
14
+ "ym:ad:<attribution>DirectSearchPhrase",
15
+ "ym:ad:<attribution>DisplayCampaign",
16
+ "ym:ad:ageInterval",
17
+ "ym:ad:gender",
18
+ "ym:ad:regionArea",
19
+ "ym:ad:regionCity",
20
+ "ym:ad:regionCitySize",
21
+ "ym:ad:regionContinent",
22
+ "ym:ad:regionCountry",
23
+ "ym:ad:regionDistrict",
24
+ "ym:dl:ageInterval",
25
+ "ym:dl:browser",
26
+ "ym:dl:browserAndVersion",
27
+ "ym:dl:browserAndVersionMajor",
28
+ "ym:dl:browserCountry",
29
+ "ym:dl:browserDate",
30
+ "ym:dl:browserDatePeriod<group>",
31
+ "ym:dl:browserDateTime",
32
+ "ym:dl:browserDayOfMonth",
33
+ "ym:dl:browserDayOfWeek",
34
+ "ym:dl:browserDekaminute",
35
+ "ym:dl:browserEngine",
36
+ "ym:dl:browserEngineVersion1",
37
+ "ym:dl:browserEngineVersion2",
38
+ "ym:dl:browserEngineVersion3",
39
+ "ym:dl:browserEngineVersion4",
40
+ "ym:dl:browserHour",
41
+ "ym:dl:browserHourMinute",
42
+ "ym:dl:browserLanguage",
43
+ "ym:dl:browserMinute",
44
+ "ym:dl:browserMonth",
45
+ "ym:dl:browserStartOfDekaminute",
46
+ "ym:dl:browserStartOfHour",
47
+ "ym:dl:browserStartOfMinute",
48
+ "ym:dl:browserStartOfMonth",
49
+ "ym:dl:browserStartOfQuarter",
50
+ "ym:dl:browserStartOfWeek",
51
+ "ym:dl:browserStartOfYear",
52
+ "ym:dl:browserYear",
53
+ "ym:dl:clientTimeZone",
54
+ "ym:dl:cookieEnabled",
55
+ "ym:dl:date",
56
+ "ym:dl:datePeriod<group>",
57
+ "ym:dl:dateTime",
58
+ "ym:dl:dayOfMonth",
59
+ "ym:dl:dayOfWeek",
60
+ "ym:dl:dekaminute",
61
+ "ym:dl:deviceCategory",
62
+ "ym:dl:downloadURL",
63
+ "ym:dl:from",
64
+ "ym:dl:gender",
65
+ "ym:dl:hasAdBlocker",
66
+ "ym:dl:hasGCLID",
67
+ "ym:dl:hasSBCLID",
68
+ "ym:dl:hour",
69
+ "ym:dl:hourMinute",
70
+ "ym:dl:ipAddress",
71
+ "ym:dl:javascriptEnabled",
72
+ "ym:dl:minute",
73
+ "ym:dl:mobilePhone",
74
+ "ym:dl:mobilePhoneModel",
75
+ "ym:dl:month",
76
+ "ym:dl:openstatAd",
77
+ "ym:dl:openstatCampaign",
78
+ "ym:dl:openstatService",
79
+ "ym:dl:openstatSource",
80
+ "ym:dl:operatingSystem",
81
+ "ym:dl:operatingSystemRoot",
82
+ "ym:dl:pageURL",
83
+ "ym:dl:physicalScreenHeight",
84
+ "ym:dl:physicalScreenResolution",
85
+ "ym:dl:physicalScreenWidth",
86
+ "ym:dl:regionArea",
87
+ "ym:dl:regionCity",
88
+ "ym:dl:regionCitySize",
89
+ "ym:dl:regionContinent",
90
+ "ym:dl:regionCountry",
91
+ "ym:dl:regionDistrict",
92
+ "ym:dl:SBCLID",
93
+ "ym:dl:screenColors",
94
+ "ym:dl:screenFormat",
95
+ "ym:dl:screenHeight",
96
+ "ym:dl:screenOrientation",
97
+ "ym:dl:screenResolution",
98
+ "ym:dl:screenWidth",
99
+ "ym:dl:startOfDekaminute",
100
+ "ym:dl:startOfHour",
101
+ "ym:dl:startOfMinute",
102
+ "ym:dl:startOfMonth",
103
+ "ym:dl:startOfQuarter",
104
+ "ym:dl:startOfWeek",
105
+ "ym:dl:startOfYear",
106
+ "ym:dl:thirdPartyCookieEnabled",
107
+ "ym:dl:title",
108
+ "ym:dl:URL",
109
+ "ym:dl:URLDomain",
110
+ "ym:dl:URLParamName",
111
+ "ym:dl:URLParamNameAndValue",
112
+ "ym:dl:URLParamValue",
113
+ "ym:dl:URLPath",
114
+ "ym:dl:URLPathFull",
115
+ "ym:dl:URLPathLevel1",
116
+ "ym:dl:URLPathLevel2",
117
+ "ym:dl:URLPathLevel3",
118
+ "ym:dl:URLPathLevel4",
119
+ "ym:dl:URLPathLevel5",
120
+ "ym:dl:URLProto",
121
+ "ym:dl:UTMCampaign",
122
+ "ym:dl:UTMContent",
123
+ "ym:dl:UTMMedium",
124
+ "ym:dl:UTMSource",
125
+ "ym:dl:UTMTerm",
126
+ "ym:dl:windowClientArea",
127
+ "ym:dl:windowClientHeight",
128
+ "ym:dl:windowClientWidth",
129
+ "ym:dl:year",
130
+ "ym:ep:actionGoal",
131
+ "ym:ep:ageInterval",
132
+ "ym:ep:browser",
133
+ "ym:ep:browserAndVersion",
134
+ "ym:ep:browserAndVersionMajor",
135
+ "ym:ep:browserDate",
136
+ "ym:ep:browserDatePeriod<group>",
137
+ "ym:ep:browserDateTime",
138
+ "ym:ep:browserDayOfMonth",
139
+ "ym:ep:browserDayOfWeek",
140
+ "ym:ep:browserDekaminute",
141
+ "ym:ep:browserEngine",
142
+ "ym:ep:browserEngineVersion1",
143
+ "ym:ep:browserEngineVersion2",
144
+ "ym:ep:browserEngineVersion3",
145
+ "ym:ep:browserEngineVersion4",
146
+ "ym:ep:browserHour",
147
+ "ym:ep:browserHourMinute",
148
+ "ym:ep:browserMinute",
149
+ "ym:ep:browserMonth",
150
+ "ym:ep:browserStartOfDekaminute",
151
+ "ym:ep:browserStartOfHour",
152
+ "ym:ep:browserStartOfMinute",
153
+ "ym:ep:browserStartOfMonth",
154
+ "ym:ep:browserStartOfQuarter",
155
+ "ym:ep:browserStartOfWeek",
156
+ "ym:ep:browserStartOfYear",
157
+ "ym:ep:browserYear",
158
+ "ym:ep:cookieEnabled",
159
+ "ym:ep:date",
160
+ "ym:ep:datePeriod<group>",
161
+ "ym:ep:dateTime",
162
+ "ym:ep:dayOfMonth",
163
+ "ym:ep:dayOfWeek",
164
+ "ym:ep:dekaminute",
165
+ "ym:ep:deviceCategory",
166
+ "ym:ep:eventParamsLevel1",
167
+ "ym:ep:eventParamsLevel10",
168
+ "ym:ep:eventParamsLevel2",
169
+ "ym:ep:eventParamsLevel3",
170
+ "ym:ep:eventParamsLevel4",
171
+ "ym:ep:eventParamsLevel5",
172
+ "ym:ep:eventParamsLevel6",
173
+ "ym:ep:eventParamsLevel7",
174
+ "ym:ep:eventParamsLevel8",
175
+ "ym:ep:eventParamsLevel9",
176
+ "ym:ep:eventURL",
177
+ "ym:ep:eventURLDomain",
178
+ "ym:ep:eventURLParamName",
179
+ "ym:ep:eventURLParamNameAndValue",
180
+ "ym:ep:eventURLParamValue",
181
+ "ym:ep:eventURLPath",
182
+ "ym:ep:eventURLPathFull",
183
+ "ym:ep:eventURLPathLevel1",
184
+ "ym:ep:eventURLPathLevel2",
185
+ "ym:ep:eventURLPathLevel3",
186
+ "ym:ep:eventURLPathLevel4",
187
+ "ym:ep:eventURLPathLevel5",
188
+ "ym:ep:eventURLProto",
189
+ "ym:ep:gender",
190
+ "ym:ep:hasAdBlocker",
191
+ "ym:ep:hour",
192
+ "ym:ep:hourMinute",
193
+ "ym:ep:ipAddress",
194
+ "ym:ep:javascriptEnabled",
195
+ "ym:ep:minute",
196
+ "ym:ep:mobilePhone",
197
+ "ym:ep:mobilePhoneModel",
198
+ "ym:ep:month",
199
+ "ym:ep:operatingSystem",
200
+ "ym:ep:operatingSystemRoot",
201
+ "ym:ep:physicalScreenHeight",
202
+ "ym:ep:physicalScreenResolution",
203
+ "ym:ep:physicalScreenWidth",
204
+ "ym:ep:regionArea",
205
+ "ym:ep:regionCity",
206
+ "ym:ep:regionCitySize",
207
+ "ym:ep:regionContinent",
208
+ "ym:ep:regionCountry",
209
+ "ym:ep:regionDistrict",
210
+ "ym:ep:screenColors",
211
+ "ym:ep:screenFormat",
212
+ "ym:ep:screenHeight",
213
+ "ym:ep:screenOrientation",
214
+ "ym:ep:screenResolution",
215
+ "ym:ep:screenWidth",
216
+ "ym:ep:startOfDekaminute",
217
+ "ym:ep:startOfHour",
218
+ "ym:ep:startOfMinute",
219
+ "ym:ep:startOfMonth",
220
+ "ym:ep:startOfQuarter",
221
+ "ym:ep:startOfWeek",
222
+ "ym:ep:startOfYear",
223
+ "ym:ep:thirdPartyCookieEnabled",
224
+ "ym:ep:windowClientArea",
225
+ "ym:ep:windowClientHeight",
226
+ "ym:ep:windowClientWidth",
227
+ "ym:ep:year",
228
+ "ym:ev:<attribution>ExpenseCampaign",
229
+ "ym:ev:<attribution>ExpenseContent",
230
+ "ym:ev:<attribution>ExpenseMedium",
231
+ "ym:ev:<attribution>ExpenseSource",
232
+ "ym:ev:<attribution>ExpenseTerm",
233
+ "ym:ev:<attribution>SourceEngine",
234
+ "ym:ev:<attribution>TrafficSource",
235
+ "ym:pv:ageInterval",
236
+ "ym:pv:browser",
237
+ "ym:pv:browserAndVersion",
238
+ "ym:pv:browserAndVersionMajor",
239
+ "ym:pv:browserCountry",
240
+ "ym:pv:browserDate",
241
+ "ym:pv:browserDatePeriod<group>",
242
+ "ym:pv:browserDateTime",
243
+ "ym:pv:browserDayOfMonth",
244
+ "ym:pv:browserDayOfWeek",
245
+ "ym:pv:browserDekaminute",
246
+ "ym:pv:browserEngine",
247
+ "ym:pv:browserEngineVersion1",
248
+ "ym:pv:browserEngineVersion2",
249
+ "ym:pv:browserEngineVersion3",
250
+ "ym:pv:browserEngineVersion4",
251
+ "ym:pv:browserHour",
252
+ "ym:pv:browserHourMinute",
253
+ "ym:pv:browserLanguage",
254
+ "ym:pv:browserMinute",
255
+ "ym:pv:browserMonth",
256
+ "ym:pv:browserStartOfDekaminute",
257
+ "ym:pv:browserStartOfHour",
258
+ "ym:pv:browserStartOfMinute",
259
+ "ym:pv:browserStartOfMonth",
260
+ "ym:pv:browserStartOfQuarter",
261
+ "ym:pv:browserStartOfWeek",
262
+ "ym:pv:browserStartOfYear",
263
+ "ym:pv:browserYear",
264
+ "ym:pv:clientTimeZone",
265
+ "ym:pv:cookieEnabled",
266
+ "ym:pv:counterID",
267
+ "ym:pv:date",
268
+ "ym:pv:datePeriod<group>",
269
+ "ym:pv:dateTime",
270
+ "ym:pv:dayOfMonth",
271
+ "ym:pv:dayOfWeek",
272
+ "ym:pv:dekaminute",
273
+ "ym:pv:deviceCategory",
274
+ "ym:pv:from",
275
+ "ym:pv:gender",
276
+ "ym:pv:hasAdBlocker",
277
+ "ym:pv:hasGCLID",
278
+ "ym:pv:hasSBCLID",
279
+ "ym:pv:hour",
280
+ "ym:pv:hourMinute",
281
+ "ym:pv:ipAddress",
282
+ "ym:pv:isTurboPage",
283
+ "ym:pv:javascriptEnabled",
284
+ "ym:pv:minute",
285
+ "ym:pv:mobilePhone",
286
+ "ym:pv:mobilePhoneModel",
287
+ "ym:pv:month",
288
+ "ym:pv:openstatAd",
289
+ "ym:pv:openstatCampaign",
290
+ "ym:pv:openstatService",
291
+ "ym:pv:openstatSource",
292
+ "ym:pv:operatingSystem",
293
+ "ym:pv:operatingSystemRoot",
294
+ "ym:pv:physicalScreenHeight",
295
+ "ym:pv:physicalScreenResolution",
296
+ "ym:pv:physicalScreenWidth",
297
+ "ym:pv:referer",
298
+ "ym:pv:refererDomain",
299
+ "ym:pv:refererPath",
300
+ "ym:pv:refererPathFull",
301
+ "ym:pv:refererPathLevel1",
302
+ "ym:pv:refererPathLevel2",
303
+ "ym:pv:refererPathLevel3",
304
+ "ym:pv:refererPathLevel4",
305
+ "ym:pv:refererPathLevel5",
306
+ "ym:pv:refererProto",
307
+ "ym:pv:regionArea",
308
+ "ym:pv:regionCity",
309
+ "ym:pv:regionCitySize",
310
+ "ym:pv:regionContinent",
311
+ "ym:pv:regionCountry",
312
+ "ym:pv:regionDistrict",
313
+ "ym:pv:SBCLID",
314
+ "ym:pv:screenColors",
315
+ "ym:pv:screenFormat",
316
+ "ym:pv:screenHeight",
317
+ "ym:pv:screenOrientation",
318
+ "ym:pv:screenResolution",
319
+ "ym:pv:screenWidth",
320
+ "ym:pv:startOfDekaminute",
321
+ "ym:pv:startOfHour",
322
+ "ym:pv:startOfMinute",
323
+ "ym:pv:startOfMonth",
324
+ "ym:pv:startOfQuarter",
325
+ "ym:pv:startOfWeek",
326
+ "ym:pv:startOfYear",
327
+ "ym:pv:thirdPartyCookieEnabled",
328
+ "ym:pv:title",
329
+ "ym:pv:URL",
330
+ "ym:pv:URLDomain",
331
+ "ym:pv:URLParamName",
332
+ "ym:pv:URLParamNameAndValue",
333
+ "ym:pv:URLParamValue",
334
+ "ym:pv:URLPath",
335
+ "ym:pv:URLPathFull",
336
+ "ym:pv:URLPathLevel1",
337
+ "ym:pv:URLPathLevel2",
338
+ "ym:pv:URLPathLevel3",
339
+ "ym:pv:URLPathLevel4",
340
+ "ym:pv:URLPathLevel5",
341
+ "ym:pv:URLProto",
342
+ "ym:pv:UTMCampaign",
343
+ "ym:pv:UTMContent",
344
+ "ym:pv:UTMMedium",
345
+ "ym:pv:UTMSource",
346
+ "ym:pv:UTMTerm",
347
+ "ym:pv:windowClientArea",
348
+ "ym:pv:windowClientHeight",
349
+ "ym:pv:windowClientWidth",
350
+ "ym:pv:year",
351
+ "ym:s:<attribution>AdvEngine",
352
+ "ym:s:<attribution>Currency",
353
+ "ym:s:<attribution>DirectBannerGroup",
354
+ "ym:s:<attribution>DirectClickBanner",
355
+ "ym:s:<attribution>DirectClickOrder",
356
+ "ym:s:<attribution>DirectConditionType",
357
+ "ym:s:<attribution>DirectID",
358
+ "ym:s:<attribution>DirectPhraseOrCond",
359
+ "ym:s:<attribution>DirectPlatform",
360
+ "ym:s:<attribution>DirectPlatformType",
361
+ "ym:s:<attribution>DirectSearchPhrase",
362
+ "ym:s:<attribution>DisplayCampaign",
363
+ "ym:s:<attribution>From",
364
+ "ym:s:<attribution>HasGCLID",
365
+ "ym:s:<attribution>HasSBCLID",
366
+ "ym:s:<attribution>Messenger",
367
+ "ym:s:<attribution>OpenstatAd",
368
+ "ym:s:<attribution>OpenstatCampaign",
369
+ "ym:s:<attribution>OpenstatService",
370
+ "ym:s:<attribution>OpenstatSource",
371
+ "ym:s:<attribution>QRCodeProvider",
372
+ "ym:s:<attribution>RecommendationSystem",
373
+ "ym:s:<attribution>ReferalSource",
374
+ "ym:s:<attribution>SBCLID",
375
+ "ym:s:<attribution>SearchEngineRoot",
376
+ "ym:s:<attribution>SearchPhrase",
377
+ "ym:s:<attribution>SocialNetwork",
378
+ "ym:s:<attribution>SocialNetworkProfile",
379
+ "ym:s:<attribution>SourceEngine",
380
+ "ym:s:<attribution>TrafficSource",
381
+ "ym:s:<attribution>UTMCampaign",
382
+ "ym:s:<attribution>UTMContent",
383
+ "ym:s:<attribution>UTMMedium",
384
+ "ym:s:<attribution>UTMSource",
385
+ "ym:s:<attribution>UTMTerm",
386
+ "ym:s:<attribution>YandexRythmDetailed",
387
+ "ym:s:adfoxBanner",
388
+ "ym:s:adfoxBannerType",
389
+ "ym:s:adfoxCampaign",
390
+ "ym:s:adfoxHeaderBidding",
391
+ "ym:s:adfoxLevel1",
392
+ "ym:s:adfoxLevel1Chained",
393
+ "ym:s:adfoxLevel2",
394
+ "ym:s:adfoxLevel2Chained",
395
+ "ym:s:adfoxLevel3Chained",
396
+ "ym:s:adfoxLevel4Chained",
397
+ "ym:s:adfoxOwner",
398
+ "ym:s:adfoxPlace",
399
+ "ym:s:adfoxPuidKey",
400
+ "ym:s:adfoxPuidValue",
401
+ "ym:s:adfoxSection",
402
+ "ym:s:adfoxSite",
403
+ "ym:s:adfoxUrlPathLevel1",
404
+ "ym:s:adfoxUrlPathLevel2",
405
+ "ym:s:adfoxUrlPathLevel3",
406
+ "ym:s:adfoxUrlPathLevel4",
407
+ "ym:s:adfoxYanImp",
408
+ "ym:s:adfoxYanPage",
409
+ "ym:s:ageInterval",
410
+ "ym:s:bounce",
411
+ "ym:s:browser",
412
+ "ym:s:browserAndVersion",
413
+ "ym:s:browserAndVersionMajor",
414
+ "ym:s:browserCountry",
415
+ "ym:s:browserDate",
416
+ "ym:s:browserDatePeriod<group>",
417
+ "ym:s:browserDateTime",
418
+ "ym:s:browserDayOfMonth",
419
+ "ym:s:browserDayOfWeek",
420
+ "ym:s:browserDekaminute",
421
+ "ym:s:browserEngine",
422
+ "ym:s:browserEngineVersion1",
423
+ "ym:s:browserEngineVersion2",
424
+ "ym:s:browserEngineVersion3",
425
+ "ym:s:browserEngineVersion4",
426
+ "ym:s:browserHour",
427
+ "ym:s:browserHourMinute",
428
+ "ym:s:browserLanguage",
429
+ "ym:s:browserMinute",
430
+ "ym:s:browserMonth",
431
+ "ym:s:browserStartOfDekaminute",
432
+ "ym:s:browserStartOfHour",
433
+ "ym:s:browserStartOfMinute",
434
+ "ym:s:browserStartOfMonth",
435
+ "ym:s:browserStartOfQuarter",
436
+ "ym:s:browserStartOfWeek",
437
+ "ym:s:browserStartOfYear",
438
+ "ym:s:browserYear",
439
+ "ym:s:clientID",
440
+ "ym:s:clientTimeZone",
441
+ "ym:s:cookieEnabled",
442
+ "ym:s:counterID",
443
+ "ym:s:date",
444
+ "ym:s:datePeriod<group>",
445
+ "ym:s:dateTime",
446
+ "ym:s:dayOfMonth",
447
+ "ym:s:dayOfWeek",
448
+ "ym:s:daysSinceFirstVisit",
449
+ "ym:s:daysSinceFirstVisitInterval",
450
+ "ym:s:daysSincePreviousVisit",
451
+ "ym:s:daysSincePreviousVisitInterval",
452
+ "ym:s:dekaminute",
453
+ "ym:s:deviceCategory",
454
+ "ym:s:endURL",
455
+ "ym:s:endURLDomain",
456
+ "ym:s:endURLPath",
457
+ "ym:s:endURLPathFull",
458
+ "ym:s:endURLPathLevel1",
459
+ "ym:s:endURLPathLevel2",
460
+ "ym:s:endURLPathLevel3",
461
+ "ym:s:endURLPathLevel4",
462
+ "ym:s:endURLPathLevel5",
463
+ "ym:s:endURLProto",
464
+ "ym:s:EPromotionCreative",
465
+ "ym:s:EPromotionCreativeSlot",
466
+ "ym:s:EPromotionEventURL",
467
+ "ym:s:EPromotionID",
468
+ "ym:s:EPromotionName",
469
+ "ym:s:EPromotionPosition",
470
+ "ym:s:experimentAB<experiment_ab>",
471
+ "ym:s:externalReferer",
472
+ "ym:s:externalRefererDomain",
473
+ "ym:s:externalRefererPath",
474
+ "ym:s:externalRefererPathFull",
475
+ "ym:s:externalRefererPathLevel1",
476
+ "ym:s:externalRefererPathLevel2",
477
+ "ym:s:externalRefererPathLevel3",
478
+ "ym:s:externalRefererPathLevel4",
479
+ "ym:s:externalRefererPathLevel5",
480
+ "ym:s:externalRefererProto",
481
+ "ym:s:firstVisitDate",
482
+ "ym:s:firstVisitDatePeriod<group>",
483
+ "ym:s:firstVisitDateTime",
484
+ "ym:s:firstVisitDayOfMonth",
485
+ "ym:s:firstVisitDayOfWeek",
486
+ "ym:s:firstVisitDekaminute",
487
+ "ym:s:firstVisitHour",
488
+ "ym:s:firstVisitHourMinute",
489
+ "ym:s:firstVisitMinute",
490
+ "ym:s:firstVisitMonth",
491
+ "ym:s:firstVisitStartOfDekaminute",
492
+ "ym:s:firstVisitStartOfHour",
493
+ "ym:s:firstVisitStartOfMinute",
494
+ "ym:s:firstVisitStartOfMonth",
495
+ "ym:s:firstVisitStartOfQuarter",
496
+ "ym:s:firstVisitStartOfWeek",
497
+ "ym:s:firstVisitStartOfYear",
498
+ "ym:s:firstVisitYear",
499
+ "ym:s:gender",
500
+ "ym:s:goal",
501
+ "ym:s:hasAdBlocker",
502
+ "ym:s:hour",
503
+ "ym:s:hourMinute",
504
+ "ym:s:interest",
505
+ "ym:s:interest2d1",
506
+ "ym:s:interest2d2",
507
+ "ym:s:interest2d3",
508
+ "ym:s:ipAddress",
509
+ "ym:s:isNewUser",
510
+ "ym:s:isRobot",
511
+ "ym:s:isRobotPro",
512
+ "ym:s:isTurboPage",
513
+ "ym:s:javascriptEnabled",
514
+ "ym:s:marketSearchPhrase",
515
+ "ym:s:minute",
516
+ "ym:s:mobilePhone",
517
+ "ym:s:mobilePhoneModel",
518
+ "ym:s:month",
519
+ "ym:s:offlineCallFirstTimeCaller",
520
+ "ym:s:offlineCallHoldDuration",
521
+ "ym:s:offlineCallMissed",
522
+ "ym:s:offlineCallTag",
523
+ "ym:s:offlineCallTalkDuration",
524
+ "ym:s:offlineChatAnswered",
525
+ "ym:s:offlineChatPlatform",
526
+ "ym:s:offlineChatTag",
527
+ "ym:s:operatingSystem",
528
+ "ym:s:operatingSystemRoot",
529
+ "ym:s:originalBounce",
530
+ "ym:s:originalPageViews",
531
+ "ym:s:originalVisitDuration",
532
+ "ym:s:originalVisitDurationInterval",
533
+ "ym:s:pageViews",
534
+ "ym:s:pageViewsInterval",
535
+ "ym:s:paramsLevel1",
536
+ "ym:s:paramsLevel10",
537
+ "ym:s:paramsLevel2",
538
+ "ym:s:paramsLevel3",
539
+ "ym:s:paramsLevel4",
540
+ "ym:s:paramsLevel5",
541
+ "ym:s:paramsLevel6",
542
+ "ym:s:paramsLevel7",
543
+ "ym:s:paramsLevel8",
544
+ "ym:s:paramsLevel9",
545
+ "ym:s:physicalScreenHeight",
546
+ "ym:s:physicalScreenResolution",
547
+ "ym:s:physicalScreenWidth",
548
+ "ym:s:PProductBrand",
549
+ "ym:s:PProductID",
550
+ "ym:s:PProductName",
551
+ "ym:s:previousVisitDate",
552
+ "ym:s:previousVisitDatePeriod<group>",
553
+ "ym:s:previousVisitDayOfMonth",
554
+ "ym:s:previousVisitDayOfWeek",
555
+ "ym:s:previousVisitMonth",
556
+ "ym:s:previousVisitStartOfMonth",
557
+ "ym:s:previousVisitStartOfQuarter",
558
+ "ym:s:previousVisitStartOfWeek",
559
+ "ym:s:previousVisitStartOfYear",
560
+ "ym:s:previousVisitYear",
561
+ "ym:s:productBrand",
562
+ "ym:s:productBrandCart",
563
+ "ym:s:productCategoryLevel1",
564
+ "ym:s:productCategoryLevel2",
565
+ "ym:s:productCategoryLevel3",
566
+ "ym:s:productCategoryLevel4",
567
+ "ym:s:productCategoryLevel5",
568
+ "ym:s:productCoupon",
569
+ "ym:s:productCurrency",
570
+ "ym:s:productDiscount",
571
+ "ym:s:productEventType",
572
+ "ym:s:productEventURL",
573
+ "ym:s:productID",
574
+ "ym:s:productIDCart",
575
+ "ym:s:productList",
576
+ "ym:s:productName",
577
+ "ym:s:productNameCart",
578
+ "ym:s:productPosition",
579
+ "ym:s:productPrice",
580
+ "ym:s:productSum",
581
+ "ym:s:productVariant",
582
+ "ym:s:publisherArticleAuthor",
583
+ "ym:s:publisherArticleFromTitle",
584
+ "ym:s:publisherArticleHasFullRead",
585
+ "ym:s:publisherArticleHasFullScroll",
586
+ "ym:s:publisherArticleHasRecircled",
587
+ "ym:s:publisherArticlePublishedDate",
588
+ "ym:s:publisherArticleReadPart",
589
+ "ym:s:publisherArticleRubric",
590
+ "ym:s:publisherArticleRubric2",
591
+ "ym:s:publisherArticleScrollDown",
592
+ "ym:s:publisherArticleTitle",
593
+ "ym:s:publisherArticleTopic",
594
+ "ym:s:publisherArticleURL",
595
+ "ym:s:publisherLongArticle",
596
+ "ym:s:publisherPageFormat",
597
+ "ym:s:publisherTrafficSource",
598
+ "ym:s:publisherTrafficSource2",
599
+ "ym:s:purchaseCoupon",
600
+ "ym:s:purchaseExistsVisit",
601
+ "ym:s:purchaseID",
602
+ "ym:s:purchaseRevenue",
603
+ "ym:s:purchaseRevenueVisit",
604
+ "ym:s:referer",
605
+ "ym:s:refererDomain",
606
+ "ym:s:refererPath",
607
+ "ym:s:refererPathFull",
608
+ "ym:s:refererPathLevel1",
609
+ "ym:s:refererPathLevel2",
610
+ "ym:s:refererPathLevel3",
611
+ "ym:s:refererPathLevel4",
612
+ "ym:s:refererPathLevel5",
613
+ "ym:s:refererProto",
614
+ "ym:s:regionArea",
615
+ "ym:s:regionCity",
616
+ "ym:s:regionCitySize",
617
+ "ym:s:regionContinent",
618
+ "ym:s:regionCountry",
619
+ "ym:s:regionDistrict",
620
+ "ym:s:RWArticleURLHash",
621
+ "ym:s:RWArticleURLPathLevel1Hash",
622
+ "ym:s:RWArticleURLPathLevel2Hash",
623
+ "ym:s:RWArticleURLPathLevel3Hash",
624
+ "ym:s:RWArticleURLPathLevel4Hash",
625
+ "ym:s:RWArticleURLPathLevel5Hash",
626
+ "ym:s:RWConversion",
627
+ "ym:s:RWURLHash",
628
+ "ym:s:RWURLPathLevel1Hash",
629
+ "ym:s:RWURLPathLevel2Hash",
630
+ "ym:s:RWURLPathLevel3Hash",
631
+ "ym:s:RWURLPathLevel4Hash",
632
+ "ym:s:RWURLPathLevel5Hash",
633
+ "ym:s:screenColors",
634
+ "ym:s:screenFormat",
635
+ "ym:s:screenHeight",
636
+ "ym:s:screenOrientation",
637
+ "ym:s:screenResolution",
638
+ "ym:s:screenWidth",
639
+ "ym:s:startOfDekaminute",
640
+ "ym:s:startOfHour",
641
+ "ym:s:startOfMinute",
642
+ "ym:s:startOfMonth",
643
+ "ym:s:startOfQuarter",
644
+ "ym:s:startOfWeek",
645
+ "ym:s:startOfYear",
646
+ "ym:s:startURL",
647
+ "ym:s:startURLDomain",
648
+ "ym:s:startURLPath",
649
+ "ym:s:startURLPathFull",
650
+ "ym:s:startURLPathLevel1",
651
+ "ym:s:startURLPathLevel2",
652
+ "ym:s:startURLPathLevel3",
653
+ "ym:s:startURLPathLevel4",
654
+ "ym:s:startURLPathLevel5",
655
+ "ym:s:startURLProto",
656
+ "ym:s:thirdPartyCookieEnabled",
657
+ "ym:s:topLevelDomain",
658
+ "ym:s:userClientUserId",
659
+ "ym:s:userParamsLevel1",
660
+ "ym:s:userParamsLevel2",
661
+ "ym:s:userParamsLevel3",
662
+ "ym:s:userParamsLevel4",
663
+ "ym:s:userParamsLevel5",
664
+ "ym:s:userVisits",
665
+ "ym:s:userVisitsInterval",
666
+ "ym:s:userVisitsPeriod",
667
+ "ym:s:userVisitsPeriodInterval",
668
+ "ym:s:vacuumEvent",
669
+ "ym:s:vacuumOrganization",
670
+ "ym:s:vacuumSurface",
671
+ "ym:s:visitDuration",
672
+ "ym:s:visitDurationInterval",
673
+ "ym:s:windowClientArea",
674
+ "ym:s:windowClientHeight",
675
+ "ym:s:windowClientWidth",
676
+ "ym:s:yanBlockID",
677
+ "ym:s:yanBlockSize",
678
+ "ym:s:yanPageID",
679
+ "ym:s:yanUrl",
680
+ "ym:s:yanUrlPathLevel1",
681
+ "ym:s:yanUrlPathLevel2",
682
+ "ym:s:yanUrlPathLevel3",
683
+ "ym:s:yanUrlPathLevel4",
684
+ "ym:s:year",
685
+ "ym:up:paramsLevel1",
686
+ "ym:up:paramsLevel2",
687
+ "ym:up:paramsLevel3",
688
+ "ym:up:paramsLevel4",
689
+ "ym:up:paramsLevel5"
690
+ ]);
691
+ var METRIC_IDS = /* @__PURE__ */ new Set([
692
+ "ym:ad:<currency>ConvertedAdCost",
693
+ "ym:ad:<currency>ConvertedAdCostPerVisit",
694
+ "ym:ad:affinityIndexInterests",
695
+ "ym:ad:affinityIndexInterests2",
696
+ "ym:ad:anyGoalConversionRate",
697
+ "ym:ad:anyGoalConverted<currency>Revenue",
698
+ "ym:ad:anyGoalReaches",
699
+ "ym:ad:anyGoalReachesPerUser",
700
+ "ym:ad:anyGoalUserConversionRate",
701
+ "ym:ad:anyGoalUsers",
702
+ "ym:ad:anyGoalVisits",
703
+ "ym:ad:avgDaysBetweenVisits",
704
+ "ym:ad:avgDaysSinceFirstVisit",
705
+ "ym:ad:avgParams",
706
+ "ym:ad:avgVisitDurationSeconds",
707
+ "ym:ad:blockedPercentage",
708
+ "ym:ad:bounceRate",
709
+ "ym:ad:clicks",
710
+ "ym:ad:cookieEnabledPercentage",
711
+ "ym:ad:ecommerce<currency>ConvertedRevenue",
712
+ "ym:ad:ecommerce<currency>ConvertedRevenuePerPurchase",
713
+ "ym:ad:ecommerce<currency>ConvertedRevenuePerVisit",
714
+ "ym:ad:ecommerceCartPercents",
715
+ "ym:ad:ecommerceCartVisits",
716
+ "ym:ad:ecommerceDetailsPercents",
717
+ "ym:ad:ecommerceDetailsVisits",
718
+ "ym:ad:ecommercePurchasePercents",
719
+ "ym:ad:ecommercePurchases",
720
+ "ym:ad:ecommercePurchaseVisits",
721
+ "ym:ad:ePromotionClicks",
722
+ "ym:ad:ePromotionClicksUniq",
723
+ "ym:ad:ePromotionClicksUserPercentage",
724
+ "ym:ad:ePromotionImpressions",
725
+ "ym:ad:ePromotionImpressionsUniq",
726
+ "ym:ad:ePromotionImpressionsUserPercentage",
727
+ "ym:ad:favoriteGoalsConversionRate",
728
+ "ym:ad:favoriteGoalsConverted<currency>Revenue",
729
+ "ym:ad:favoriteGoalsConverted<currency>RevenuePerVisit",
730
+ "ym:ad:favoriteGoalsReaches",
731
+ "ym:ad:favoriteGoalsReachesPerUser",
732
+ "ym:ad:favoriteGoalsUserConversionRate",
733
+ "ym:ad:favoriteGoalsUsers",
734
+ "ym:ad:favoriteGoalsVisits",
735
+ "ym:ad:GCLIDPercentage",
736
+ "ym:ad:goal<goal_id>conversionRate",
737
+ "ym:ad:goal<goal_id>converted<currency>AdCostPerVisit",
738
+ "ym:ad:goal<goal_id>converted<currency>CPA",
739
+ "ym:ad:goal<goal_id>converted<currency>Revenue",
740
+ "ym:ad:goal<goal_id>reaches",
741
+ "ym:ad:goal<goal_id>reachesPerUser",
742
+ "ym:ad:goal<goal_id>userConversionRate",
743
+ "ym:ad:goal<goal_id>users",
744
+ "ym:ad:goal<goal_id>visits",
745
+ "ym:ad:jsEnabledPercentage",
746
+ "ym:ad:manPercentage",
747
+ "ym:ad:mobilePercentage",
748
+ "ym:ad:newUsers",
749
+ "ym:ad:newUserVisitsPercentage",
750
+ "ym:ad:oneDayBetweenVisitsPercentage",
751
+ "ym:ad:oneVisitPerUserPercentage",
752
+ "ym:ad:over32VisitsPerUserPercentage",
753
+ "ym:ad:over54AgePercentage",
754
+ "ym:ad:overMonthBetweenVisitsPercentage",
755
+ "ym:ad:overYearSinceFirstVisitPercentage",
756
+ "ym:ad:overYearUserRecencyPercentage",
757
+ "ym:ad:pageDepth",
758
+ "ym:ad:pageviews",
759
+ "ym:ad:paramsNumber",
760
+ "ym:ad:percentNewVisitors",
761
+ "ym:ad:productBaskets<currency>ConvertedPrice",
762
+ "ym:ad:productBasketsPrice",
763
+ "ym:ad:productBasketsQuantity",
764
+ "ym:ad:productBasketsRemoveUniq",
765
+ "ym:ad:productBasketsRemoveUserPercentage",
766
+ "ym:ad:productBasketsUniq",
767
+ "ym:ad:productBasketsUserPercentage",
768
+ "ym:ad:productClicks",
769
+ "ym:ad:productClicksUniq",
770
+ "ym:ad:productClicksUserPercentage",
771
+ "ym:ad:productImpressions",
772
+ "ym:ad:productImpressionsUniq",
773
+ "ym:ad:productImpressionsUserPercentage",
774
+ "ym:ad:productInListImpressions",
775
+ "ym:ad:productInListImpressionsUniq",
776
+ "ym:ad:productInListImpressionsUserPercentage",
777
+ "ym:ad:productPurchased<currency>ConvertedPrice",
778
+ "ym:ad:productPurchasedPrice",
779
+ "ym:ad:productPurchasedQuantity",
780
+ "ym:ad:productPurchasedUniq",
781
+ "ym:ad:robotPercentage",
782
+ "ym:ad:robotVisits",
783
+ "ym:ad:sumParams",
784
+ "ym:ad:thirdPartyCookieEnabledPercentage",
785
+ "ym:ad:under18AgePercentage",
786
+ "ym:ad:upTo24AgePercentage",
787
+ "ym:ad:upTo31VisitsPerUserPercentage",
788
+ "ym:ad:upTo34AgePercentage",
789
+ "ym:ad:upTo3VisitsPerUserPercentage",
790
+ "ym:ad:upTo44AgePercentage",
791
+ "ym:ad:upTo54AgePercentage",
792
+ "ym:ad:upTo7VisitsPerUserPercentage",
793
+ "ym:ad:upToDaySinceFirstVisitPercentage",
794
+ "ym:ad:upToDayUserRecencyPercentage",
795
+ "ym:ad:upToMonthBetweenVisitsPercentage",
796
+ "ym:ad:upToMonthSinceFirstVisitPercentage",
797
+ "ym:ad:upToMonthUserRecencyPercentage",
798
+ "ym:ad:upToQuarterSinceFirstVisitPercentage",
799
+ "ym:ad:upToQuarterUserRecencyPercentage",
800
+ "ym:ad:upToWeekBetweenVisitsPercentage",
801
+ "ym:ad:upToWeekSinceFirstVisitPercentage",
802
+ "ym:ad:upToWeekUserRecencyPercentage",
803
+ "ym:ad:upToYearSinceFirstVisitPercentage",
804
+ "ym:ad:upToYearUserRecencyPercentage",
805
+ "ym:ad:userRecencyDays",
806
+ "ym:ad:users",
807
+ "ym:ad:usersPurchasePercentage",
808
+ "ym:ad:visits",
809
+ "ym:ad:visitsPerDay",
810
+ "ym:ad:visitsPerHour",
811
+ "ym:ad:visitsPerMinute",
812
+ "ym:ad:womanPercentage",
813
+ "ym:dl:blockedPercentage",
814
+ "ym:dl:cookieEnabledPercentage",
815
+ "ym:dl:downloads",
816
+ "ym:dl:jsEnabledPercentage",
817
+ "ym:dl:mobilePercentage",
818
+ "ym:dl:pageviewsPerDay",
819
+ "ym:dl:pageviewsPerHour",
820
+ "ym:dl:pageviewsPerMinute",
821
+ "ym:dl:thirdPartyCookieEnabledPercentage",
822
+ "ym:dl:users",
823
+ "ym:ep:avgEventParams",
824
+ "ym:ep:eventPageViews",
825
+ "ym:ep:eventParamsNumber",
826
+ "ym:ep:eventsNumber",
827
+ "ym:ep:sumEventParams",
828
+ "ym:ev:affinityIndexInterests",
829
+ "ym:ev:affinityIndexInterests2",
830
+ "ym:ev:anyGoalConversionRate",
831
+ "ym:ev:anyGoalConverted<currency>Revenue",
832
+ "ym:ev:anyGoalReaches",
833
+ "ym:ev:anyGoalReachesPerUser",
834
+ "ym:ev:anyGoalUserConversionRate",
835
+ "ym:ev:anyGoalUsers",
836
+ "ym:ev:anyGoalVisits",
837
+ "ym:ev:avgDaysBetweenVisits",
838
+ "ym:ev:avgDaysSinceFirstVisit",
839
+ "ym:ev:avgOriginalVisitDurationSeconds",
840
+ "ym:ev:avgParams",
841
+ "ym:ev:avgVisitDurationSeconds",
842
+ "ym:ev:blockedPercentage",
843
+ "ym:ev:bounceRate",
844
+ "ym:ev:cdpOrders<currency>AverageCheque",
845
+ "ym:ev:cdpOrders<currency>Profit",
846
+ "ym:ev:cdpOrders<currency>Revenue",
847
+ "ym:ev:cdpOrdersAllOrders",
848
+ "ym:ev:cdpOrdersCancelled",
849
+ "ym:ev:cdpOrdersConversionIntoOrder",
850
+ "ym:ev:cdpOrdersConversionIntoPayment",
851
+ "ym:ev:cdpOrdersInProgress",
852
+ "ym:ev:cdpOrdersOther",
853
+ "ym:ev:cdpOrdersPayed",
854
+ "ym:ev:cdpOrdersSpam",
855
+ "ym:ev:cookieEnabledPercentage",
856
+ "ym:ev:ecommerce<currency>ConvertedRevenue",
857
+ "ym:ev:ecommerce<currency>ConvertedRevenuePerPurchase",
858
+ "ym:ev:ecommerce<currency>ConvertedRevenuePerVisit",
859
+ "ym:ev:ecommerceCartPercents",
860
+ "ym:ev:ecommerceCartVisits",
861
+ "ym:ev:ecommerceDetailsPercents",
862
+ "ym:ev:ecommerceDetailsVisits",
863
+ "ym:ev:ecommercePurchasePercents",
864
+ "ym:ev:ecommercePurchases",
865
+ "ym:ev:ecommercePurchaseVisits",
866
+ "ym:ev:ePromotionClicks",
867
+ "ym:ev:ePromotionClicksUniq",
868
+ "ym:ev:ePromotionClicksUserPercentage",
869
+ "ym:ev:ePromotionImpressions",
870
+ "ym:ev:ePromotionImpressionsUniq",
871
+ "ym:ev:ePromotionImpressionsUserPercentage",
872
+ "ym:ev:expense<currency>CPC",
873
+ "ym:ev:expense<currency>EcommerceCPA",
874
+ "ym:ev:expense<currency>EcommerceCRR",
875
+ "ym:ev:expense<currency>EcommerceROI",
876
+ "ym:ev:expense<currency>FavoriteGoalsCPA",
877
+ "ym:ev:expense<currency>FavoriteGoalsCRR",
878
+ "ym:ev:expense<currency>FavoriteGoalsROI",
879
+ "ym:ev:expense<currency>FavoriteGoalsUserCPA",
880
+ "ym:ev:expense<currency>FavoriteGoalsVisitCPA",
881
+ "ym:ev:expenseClicks",
882
+ "ym:ev:expenses<currency>",
883
+ "ym:ev:favoriteGoalsConversionRate",
884
+ "ym:ev:favoriteGoalsConverted<currency>Revenue",
885
+ "ym:ev:favoriteGoalsConverted<currency>RevenuePerVisit",
886
+ "ym:ev:favoriteGoalsReaches",
887
+ "ym:ev:favoriteGoalsReachesPerUser",
888
+ "ym:ev:favoriteGoalsUserConversionRate",
889
+ "ym:ev:favoriteGoalsUsers",
890
+ "ym:ev:favoriteGoalsVisits",
891
+ "ym:ev:GCLIDPercentage",
892
+ "ym:ev:goal<goal_id>conversionRate",
893
+ "ym:ev:goal<goal_id>converted<currency>Revenue",
894
+ "ym:ev:goal<goal_id>expense<currency>CRR",
895
+ "ym:ev:goal<goal_id>expense<currency>ReachCPA",
896
+ "ym:ev:goal<goal_id>expense<currency>ROI",
897
+ "ym:ev:goal<goal_id>expense<currency>UserCPA",
898
+ "ym:ev:goal<goal_id>expense<currency>VisitCPA",
899
+ "ym:ev:goal<goal_id>reaches",
900
+ "ym:ev:goal<goal_id>reachesPerUser",
901
+ "ym:ev:goal<goal_id>userConversionRate",
902
+ "ym:ev:goal<goal_id>users",
903
+ "ym:ev:goal<goal_id>visits",
904
+ "ym:ev:jsEnabledPercentage",
905
+ "ym:ev:manPercentage",
906
+ "ym:ev:mobilePercentage",
907
+ "ym:ev:newUsers",
908
+ "ym:ev:newUserVisitsPercentage",
909
+ "ym:ev:oneDayBetweenVisitsPercentage",
910
+ "ym:ev:oneVisitPerUserPercentage",
911
+ "ym:ev:originalBounceRate",
912
+ "ym:ev:originalPageDepth",
913
+ "ym:ev:originalPageviews",
914
+ "ym:ev:over32VisitsPerUserPercentage",
915
+ "ym:ev:over54AgePercentage",
916
+ "ym:ev:overMonthBetweenVisitsPercentage",
917
+ "ym:ev:overYearSinceFirstVisitPercentage",
918
+ "ym:ev:overYearUserRecencyPercentage",
919
+ "ym:ev:pageDepth",
920
+ "ym:ev:pageviews",
921
+ "ym:ev:paramsNumber",
922
+ "ym:ev:percentNewVisitors",
923
+ "ym:ev:productBaskets<currency>ConvertedPrice",
924
+ "ym:ev:productBasketsPrice",
925
+ "ym:ev:productBasketsQuantity",
926
+ "ym:ev:productBasketsRemoveUniq",
927
+ "ym:ev:productBasketsRemoveUserPercentage",
928
+ "ym:ev:productBasketsUniq",
929
+ "ym:ev:productBasketsUserPercentage",
930
+ "ym:ev:productClicks",
931
+ "ym:ev:productClicksUniq",
932
+ "ym:ev:productClicksUserPercentage",
933
+ "ym:ev:productImpressions",
934
+ "ym:ev:productImpressionsUniq",
935
+ "ym:ev:productImpressionsUserPercentage",
936
+ "ym:ev:productInListImpressions",
937
+ "ym:ev:productInListImpressionsUniq",
938
+ "ym:ev:productInListImpressionsUserPercentage",
939
+ "ym:ev:productPurchased<currency>ConvertedPrice",
940
+ "ym:ev:productPurchasedPrice",
941
+ "ym:ev:productPurchasedQuantity",
942
+ "ym:ev:productPurchasedUniq",
943
+ "ym:ev:robotPercentage",
944
+ "ym:ev:robotVisits",
945
+ "ym:ev:sumParams",
946
+ "ym:ev:thirdPartyCookieEnabledPercentage",
947
+ "ym:ev:under18AgePercentage",
948
+ "ym:ev:upTo24AgePercentage",
949
+ "ym:ev:upTo31VisitsPerUserPercentage",
950
+ "ym:ev:upTo34AgePercentage",
951
+ "ym:ev:upTo3VisitsPerUserPercentage",
952
+ "ym:ev:upTo44AgePercentage",
953
+ "ym:ev:upTo54AgePercentage",
954
+ "ym:ev:upTo7VisitsPerUserPercentage",
955
+ "ym:ev:upToDaySinceFirstVisitPercentage",
956
+ "ym:ev:upToDayUserRecencyPercentage",
957
+ "ym:ev:upToMonthBetweenVisitsPercentage",
958
+ "ym:ev:upToMonthSinceFirstVisitPercentage",
959
+ "ym:ev:upToMonthUserRecencyPercentage",
960
+ "ym:ev:upToQuarterSinceFirstVisitPercentage",
961
+ "ym:ev:upToQuarterUserRecencyPercentage",
962
+ "ym:ev:upToWeekBetweenVisitsPercentage",
963
+ "ym:ev:upToWeekSinceFirstVisitPercentage",
964
+ "ym:ev:upToWeekUserRecencyPercentage",
965
+ "ym:ev:upToYearSinceFirstVisitPercentage",
966
+ "ym:ev:upToYearUserRecencyPercentage",
967
+ "ym:ev:userRecencyDays",
968
+ "ym:ev:users",
969
+ "ym:ev:usersPurchasePercentage",
970
+ "ym:ev:visits",
971
+ "ym:ev:visitsPerDay",
972
+ "ym:ev:visitsPerHour",
973
+ "ym:ev:visitsPerMinute",
974
+ "ym:ev:womanPercentage",
975
+ "ym:pv:blockedPercentage",
976
+ "ym:pv:cookieEnabledPercentage",
977
+ "ym:pv:jsEnabledPercentage",
978
+ "ym:pv:mobilePercentage",
979
+ "ym:pv:pageviews",
980
+ "ym:pv:pageviewsPerDay",
981
+ "ym:pv:pageviewsPerHour",
982
+ "ym:pv:pageviewsPerMinute",
983
+ "ym:pv:thirdPartyCookieEnabledPercentage",
984
+ "ym:pv:users",
985
+ "ym:s:adfoxARPU",
986
+ "ym:s:adfoxClicks",
987
+ "ym:s:adfoxCountEvent1",
988
+ "ym:s:adfoxCountEvent10",
989
+ "ym:s:adfoxCountEvent11",
990
+ "ym:s:adfoxCountEvent12",
991
+ "ym:s:adfoxCountEvent13",
992
+ "ym:s:adfoxCountEvent14",
993
+ "ym:s:adfoxCountEvent15",
994
+ "ym:s:adfoxCountEvent16",
995
+ "ym:s:adfoxCountEvent17",
996
+ "ym:s:adfoxCountEvent18",
997
+ "ym:s:adfoxCountEvent19",
998
+ "ym:s:adfoxCountEvent2",
999
+ "ym:s:adfoxCountEvent20",
1000
+ "ym:s:adfoxCountEvent21",
1001
+ "ym:s:adfoxCountEvent22",
1002
+ "ym:s:adfoxCountEvent23",
1003
+ "ym:s:adfoxCountEvent24",
1004
+ "ym:s:adfoxCountEvent25",
1005
+ "ym:s:adfoxCountEvent26",
1006
+ "ym:s:adfoxCountEvent27",
1007
+ "ym:s:adfoxCountEvent28",
1008
+ "ym:s:adfoxCountEvent29",
1009
+ "ym:s:adfoxCountEvent3",
1010
+ "ym:s:adfoxCountEvent30",
1011
+ "ym:s:adfoxCountEvent4",
1012
+ "ym:s:adfoxCountEvent5",
1013
+ "ym:s:adfoxCountEvent6",
1014
+ "ym:s:adfoxCountEvent7",
1015
+ "ym:s:adfoxCountEvent8",
1016
+ "ym:s:adfoxCountEvent9",
1017
+ "ym:s:adfoxCPMV",
1018
+ "ym:s:adfoxECPM",
1019
+ "ym:s:adfoxPrice",
1020
+ "ym:s:adfoxPriceGoogle",
1021
+ "ym:s:adfoxPriceHeaderBidding",
1022
+ "ym:s:adfoxPricePerHit",
1023
+ "ym:s:adfoxPricePerUser",
1024
+ "ym:s:adfoxPricePerVisit",
1025
+ "ym:s:adfoxPriceStrict",
1026
+ "ym:s:adfoxPriceYan",
1027
+ "ym:s:adfoxRenders",
1028
+ "ym:s:adfoxRendersDefault",
1029
+ "ym:s:adfoxRendersDefaultShare",
1030
+ "ym:s:adfoxRendersPerHit",
1031
+ "ym:s:adfoxRendersPerUser",
1032
+ "ym:s:adfoxRendersPerVisit",
1033
+ "ym:s:adfoxRequests",
1034
+ "ym:s:adfoxRPM",
1035
+ "ym:s:adfoxShows",
1036
+ "ym:s:adfoxVisibility",
1037
+ "ym:s:affinityIndexInterests",
1038
+ "ym:s:affinityIndexInterests2",
1039
+ "ym:s:anyGoalConversionRate",
1040
+ "ym:s:anyGoalConverted<currency>Revenue",
1041
+ "ym:s:anyGoalReaches",
1042
+ "ym:s:anyGoalReachesPerUser",
1043
+ "ym:s:anyGoalUserConversionRate",
1044
+ "ym:s:anyGoalUsers",
1045
+ "ym:s:anyGoalVisits",
1046
+ "ym:s:avgDaysBetweenVisits",
1047
+ "ym:s:avgDaysSinceFirstVisit",
1048
+ "ym:s:avgOriginalVisitDurationSeconds",
1049
+ "ym:s:avgParams",
1050
+ "ym:s:avgPublisherArticleInvolvedTimeSeconds",
1051
+ "ym:s:avgUserParams",
1052
+ "ym:s:avgVisitDurationSeconds",
1053
+ "ym:s:blockedPercentage",
1054
+ "ym:s:bounceRate",
1055
+ "ym:s:cdpOrders<currency>AverageCheque",
1056
+ "ym:s:cdpOrders<currency>Profit",
1057
+ "ym:s:cdpOrders<currency>Revenue",
1058
+ "ym:s:cdpOrdersAllOrders",
1059
+ "ym:s:cdpOrdersCancelled",
1060
+ "ym:s:cdpOrdersConversionIntoOrder",
1061
+ "ym:s:cdpOrdersConversionIntoPayment",
1062
+ "ym:s:cdpOrdersInProgress",
1063
+ "ym:s:cdpOrdersOther",
1064
+ "ym:s:cdpOrdersPayed",
1065
+ "ym:s:cdpOrdersSpam",
1066
+ "ym:s:cookieEnabledPercentage",
1067
+ "ym:s:crossDeviceUsers",
1068
+ "ym:s:ecommerce<currency>ConvertedRevenue",
1069
+ "ym:s:ecommerce<currency>ConvertedRevenuePerPurchase",
1070
+ "ym:s:ecommerce<currency>ConvertedRevenuePerVisit",
1071
+ "ym:s:ecommerceCartPercents",
1072
+ "ym:s:ecommerceCartVisits",
1073
+ "ym:s:ecommerceDetailsPercents",
1074
+ "ym:s:ecommerceDetailsVisits",
1075
+ "ym:s:ecommercePurchasePercents",
1076
+ "ym:s:ecommercePurchases",
1077
+ "ym:s:ecommercePurchaseVisits",
1078
+ "ym:s:ePromotionClicks",
1079
+ "ym:s:ePromotionClicksUniq",
1080
+ "ym:s:ePromotionClicksUserPercentage",
1081
+ "ym:s:ePromotionImpressions",
1082
+ "ym:s:ePromotionImpressionsUniq",
1083
+ "ym:s:ePromotionImpressionsUserPercentage",
1084
+ "ym:s:favoriteGoalsConversionRate",
1085
+ "ym:s:favoriteGoalsConverted<currency>Revenue",
1086
+ "ym:s:favoriteGoalsConverted<currency>RevenuePerVisit",
1087
+ "ym:s:favoriteGoalsReaches",
1088
+ "ym:s:favoriteGoalsReachesPerUser",
1089
+ "ym:s:favoriteGoalsUserConversionRate",
1090
+ "ym:s:favoriteGoalsUsers",
1091
+ "ym:s:favoriteGoalsVisits",
1092
+ "ym:s:GCLIDPercentage",
1093
+ "ym:s:goal<goal_id>conversionRate",
1094
+ "ym:s:goal<goal_id>converted<currency>Revenue",
1095
+ "ym:s:goal<goal_id>reaches",
1096
+ "ym:s:goal<goal_id>reachesPerUser",
1097
+ "ym:s:goal<goal_id>userConversionRate",
1098
+ "ym:s:goal<goal_id>users",
1099
+ "ym:s:goal<goal_id>visits",
1100
+ "ym:s:jsEnabledPercentage",
1101
+ "ym:s:manPercentage",
1102
+ "ym:s:mobilePercentage",
1103
+ "ym:s:newUsers",
1104
+ "ym:s:newUserVisitsPercentage",
1105
+ "ym:s:offlineCall<currency>ConvertedRevenue",
1106
+ "ym:s:offlineCall<currency>ConvertedRevenueAvg",
1107
+ "ym:s:offlineCallDurationAvg",
1108
+ "ym:s:offlineCallHoldDurationTillAnswerAvg",
1109
+ "ym:s:offlineCallHoldDurationTillMissAvg",
1110
+ "ym:s:offlineCalls",
1111
+ "ym:s:offlineCallsFirstTimeCaller",
1112
+ "ym:s:offlineCallsFirstTimeCallerPercentage",
1113
+ "ym:s:offlineCallsMissed",
1114
+ "ym:s:offlineCallsMissedPercentage",
1115
+ "ym:s:offlineCallsUniq",
1116
+ "ym:s:offlineCallTalkDurationAvg",
1117
+ "ym:s:offlineChats",
1118
+ "ym:s:offlineChatsMissed",
1119
+ "ym:s:offlineChatsMissedPercentage",
1120
+ "ym:s:oneDayBetweenVisitsPercentage",
1121
+ "ym:s:oneVisitPerUserPercentage",
1122
+ "ym:s:originalBounceRate",
1123
+ "ym:s:originalPageDepth",
1124
+ "ym:s:originalPageviews",
1125
+ "ym:s:over32VisitsPerUserPercentage",
1126
+ "ym:s:over54AgePercentage",
1127
+ "ym:s:overMonthBetweenVisitsPercentage",
1128
+ "ym:s:overYearSinceFirstVisitPercentage",
1129
+ "ym:s:overYearUserRecencyPercentage",
1130
+ "ym:s:pageDepth",
1131
+ "ym:s:pageviews",
1132
+ "ym:s:paramsNumber",
1133
+ "ym:s:percentNewVisitors",
1134
+ "ym:s:productBaskets<currency>ConvertedPrice",
1135
+ "ym:s:productBasketsPrice",
1136
+ "ym:s:productBasketsQuantity",
1137
+ "ym:s:productBasketsRemoveUniq",
1138
+ "ym:s:productBasketsRemoveUserPercentage",
1139
+ "ym:s:productBasketsUniq",
1140
+ "ym:s:productBasketsUserPercentage",
1141
+ "ym:s:productClicks",
1142
+ "ym:s:productClicksUniq",
1143
+ "ym:s:productClicksUserPercentage",
1144
+ "ym:s:productImpressions",
1145
+ "ym:s:productImpressionsUniq",
1146
+ "ym:s:productImpressionsUserPercentage",
1147
+ "ym:s:productInListImpressions",
1148
+ "ym:s:productInListImpressionsUniq",
1149
+ "ym:s:productInListImpressionsUserPercentage",
1150
+ "ym:s:productPurchased<currency>ConvertedPrice",
1151
+ "ym:s:productPurchasedPrice",
1152
+ "ym:s:productPurchasedQuantity",
1153
+ "ym:s:productPurchasedUniq",
1154
+ "ym:s:publisherArticleFullReadShare",
1155
+ "ym:s:publisherArticleRecirculation",
1156
+ "ym:s:publisherArticleUsersRecircled",
1157
+ "ym:s:publisherArticleViewsFullScrollShare",
1158
+ "ym:s:publisherMobileOrTabletViews",
1159
+ "ym:s:publisherMobileOrTabletViewsShare",
1160
+ "ym:s:publisherusers",
1161
+ "ym:s:publisherviews",
1162
+ "ym:s:publisherViewsFullRead",
1163
+ "ym:s:publisherViewsFullScroll",
1164
+ "ym:s:publisherviewsPerDay",
1165
+ "ym:s:publisherviewsPerHour",
1166
+ "ym:s:publisherviewsPerMinute",
1167
+ "ym:s:robotPercentage",
1168
+ "ym:s:robotProPercentage",
1169
+ "ym:s:robotVisits",
1170
+ "ym:s:rwArticleClicks",
1171
+ "ym:s:rwArticleCTR",
1172
+ "ym:s:rwArticleShows",
1173
+ "ym:s:rwArticleVisibility",
1174
+ "ym:s:rwClicksSum",
1175
+ "ym:s:rwCTR",
1176
+ "ym:s:rwShows",
1177
+ "ym:s:rwVisibility",
1178
+ "ym:s:sumParams",
1179
+ "ym:s:sumPublisherArticleInvolvedTimeSeconds",
1180
+ "ym:s:sumUserParams",
1181
+ "ym:s:thirdPartyCookieEnabledPercentage",
1182
+ "ym:s:under18AgePercentage",
1183
+ "ym:s:upTo24AgePercentage",
1184
+ "ym:s:upTo31VisitsPerUserPercentage",
1185
+ "ym:s:upTo34AgePercentage",
1186
+ "ym:s:upTo3VisitsPerUserPercentage",
1187
+ "ym:s:upTo44AgePercentage",
1188
+ "ym:s:upTo54AgePercentage",
1189
+ "ym:s:upTo7VisitsPerUserPercentage",
1190
+ "ym:s:upToDaySinceFirstVisitPercentage",
1191
+ "ym:s:upToDayUserRecencyPercentage",
1192
+ "ym:s:upToMonthBetweenVisitsPercentage",
1193
+ "ym:s:upToMonthSinceFirstVisitPercentage",
1194
+ "ym:s:upToMonthUserRecencyPercentage",
1195
+ "ym:s:upToQuarterSinceFirstVisitPercentage",
1196
+ "ym:s:upToQuarterUserRecencyPercentage",
1197
+ "ym:s:upToWeekBetweenVisitsPercentage",
1198
+ "ym:s:upToWeekSinceFirstVisitPercentage",
1199
+ "ym:s:upToWeekUserRecencyPercentage",
1200
+ "ym:s:upToYearSinceFirstVisitPercentage",
1201
+ "ym:s:upToYearUserRecencyPercentage",
1202
+ "ym:s:userParamsNumber",
1203
+ "ym:s:userRecencyDays",
1204
+ "ym:s:users",
1205
+ "ym:s:usersPurchasePercentage",
1206
+ "ym:s:vacuumevents",
1207
+ "ym:s:vacuumeventsPerUser",
1208
+ "ym:s:vacuumusers",
1209
+ "ym:s:visits",
1210
+ "ym:s:visitsPerDay",
1211
+ "ym:s:visitsPerHour",
1212
+ "ym:s:visitsPerMinute",
1213
+ "ym:s:womanPercentage",
1214
+ "ym:s:yanARPU",
1215
+ "ym:s:yanCPMV",
1216
+ "ym:s:yanECPM",
1217
+ "ym:s:yanPartnerPrice",
1218
+ "ym:s:yanRenders",
1219
+ "ym:s:yanRendersPerHit",
1220
+ "ym:s:yanRendersPerUser",
1221
+ "ym:s:yanRendersPerVisit",
1222
+ "ym:s:yanRequests",
1223
+ "ym:s:yanRevenuePerHit",
1224
+ "ym:s:yanRevenuePerVisit",
1225
+ "ym:s:yanRPM",
1226
+ "ym:s:yanShows",
1227
+ "ym:s:yanVisibility",
1228
+ "ym:up:params",
1229
+ "ym:up:users"
1230
+ ]);
1231
+ var PRESET_IDS = /* @__PURE__ */ new Set([
1232
+ "adfox_defaults",
1233
+ "adfox_geo",
1234
+ "adfox_header_bidding",
1235
+ "adfox_invent",
1236
+ "adfox_puids",
1237
+ "adfox_shows",
1238
+ "adfox_sources",
1239
+ "adfox_urls",
1240
+ "adv_engine",
1241
+ "age",
1242
+ "age_gender",
1243
+ "basket",
1244
+ "basket_products",
1245
+ "content_entrance",
1246
+ "content_exit",
1247
+ "content_user_params",
1248
+ "content_visit_params",
1249
+ "conversion",
1250
+ "coupon",
1251
+ "deepness_depth",
1252
+ "deepness_time",
1253
+ "downloads",
1254
+ "ecom_funnel",
1255
+ "event_params",
1256
+ "expenses",
1257
+ "experiment_ab",
1258
+ "gender",
1259
+ "geo_country",
1260
+ "goal_params",
1261
+ "hidden_metrics_goal",
1262
+ "hourly",
1263
+ "interests",
1264
+ "interests2",
1265
+ "loyalty_newness",
1266
+ "loyalty_period",
1267
+ "loyalty_recency",
1268
+ "loyalty_visits",
1269
+ "offline_calls_quality",
1270
+ "offline_calls_sources",
1271
+ "orders_sources",
1272
+ "popular",
1273
+ "product_list",
1274
+ "promo_campaigns",
1275
+ "publishers_authors",
1276
+ "publishers_rubrics",
1277
+ "publishers_sources",
1278
+ "publishers_thematics",
1279
+ "purchase",
1280
+ "recommendation_widget_articles",
1281
+ "recommendation_widget_conversion",
1282
+ "recommendation_widget_page",
1283
+ "resolution_map",
1284
+ "search_engines",
1285
+ "sources_direct_clicks",
1286
+ "sources_direct_platforms",
1287
+ "sources_direct_platforms_types",
1288
+ "sources_direct_summary",
1289
+ "sources_expenses_and_roi",
1290
+ "sources_messenger",
1291
+ "sources_recommend",
1292
+ "sources_search_phrases",
1293
+ "sources_sites",
1294
+ "sources_social",
1295
+ "sources_summary",
1296
+ "tags_from",
1297
+ "tags_gclid",
1298
+ "tags_openstat",
1299
+ "tags_u_t_m",
1300
+ "tech_browsers",
1301
+ "tech_cookies",
1302
+ "tech_devices",
1303
+ "tech_display",
1304
+ "tech_display_groups",
1305
+ "tech_java_script",
1306
+ "tech_platforms",
1307
+ "tech_third_party_cookies",
1308
+ "titles",
1309
+ "top_brands",
1310
+ "top_products",
1311
+ "traffic",
1312
+ "turbo_app",
1313
+ "turbo_pages",
1314
+ "url_params",
1315
+ "vacuum",
1316
+ "visits_by_client_user_id",
1317
+ "visits_by_user_param",
1318
+ "yan",
1319
+ "yan_adb",
1320
+ "yan_browsers",
1321
+ "yan_device",
1322
+ "yan_geo",
1323
+ "yan_sources",
1324
+ "yandex_rythm"
1325
+ ]);
1326
+
1327
+ // src/contract/registry.ts
1328
+ var NAMESPACE_RE = /^ym:([a-z]{1,3}):/;
1329
+ function namespaceOf(id2) {
1330
+ return NAMESPACE_RE.exec(id2)?.[1];
1331
+ }
1332
+ var DEPRECATED_ATTRIBUTIONS = {
1333
+ first: "cross_device_first",
1334
+ last_significant: "cross_device_last_significant",
1335
+ last_yandex_direct_click: "automatic"
1336
+ };
1337
+ function hasDimension(id2) {
1338
+ return DIMENSION_IDS.has(id2);
1339
+ }
1340
+ function hasMetric(id2) {
1341
+ return METRIC_IDS.has(id2);
1342
+ }
1343
+ function hasPreset(id2) {
1344
+ return PRESET_IDS.has(id2);
1345
+ }
1346
+
1347
+ // src/client/errors.ts
1348
+ var MetrikaError = class extends Error {
1349
+ status;
1350
+ errorType;
1351
+ details;
1352
+ requestUrl;
1353
+ constructor(message, options) {
1354
+ super(message);
1355
+ this.name = new.target.name;
1356
+ this.status = options.status;
1357
+ this.errorType = options.errorType;
1358
+ this.details = options.details;
1359
+ this.requestUrl = options.requestUrl;
1360
+ }
1361
+ };
1362
+ var QuotaError = class extends MetrikaError {
1363
+ /** Через сколько миллисекунд разумно повторить попытку. */
1364
+ retryAfterMs;
1365
+ constructor(message, options) {
1366
+ super(message, options);
1367
+ this.retryAfterMs = options.retryAfterMs;
1368
+ }
1369
+ };
1370
+ var AuthError = class extends MetrikaError {
1371
+ };
1372
+ var InvalidRequestError = class extends MetrikaError {
1373
+ };
1374
+ var NotFoundError = class extends MetrikaError {
1375
+ };
1376
+ var ServerError = class extends MetrikaError {
1377
+ };
1378
+ var RequestValidationError = class extends Error {
1379
+ constructor(message) {
1380
+ super(message);
1381
+ this.name = "RequestValidationError";
1382
+ }
1383
+ };
1384
+ var AUTH_TYPES = /* @__PURE__ */ new Set(["invalid_token", "unauthorized", "access_denied", "counter_in_connect"]);
1385
+ var SERVER_TYPES = /* @__PURE__ */ new Set(["backend_error", "timeout"]);
1386
+ var QUOTA_RETRY_MS = {
1387
+ quota_requests_by_ip: 1e3,
1388
+ quota_parallel_requests: 1e3,
1389
+ quota_requests_by_uid: 5 * 6e4,
1390
+ quota_requests_by_counter_id: 5 * 6e4,
1391
+ quota_delegate_requests: 60 * 6e4,
1392
+ quota_grants_requests: 60 * 6e4
1393
+ };
1394
+ function toMetrikaError(status, body, requestUrl) {
1395
+ const details = body?.errors ?? [];
1396
+ const errorType = details[0]?.error_type ?? `http_${status}`;
1397
+ const message = details[0]?.message ?? body?.message ?? `\u0417\u0430\u043F\u0440\u043E\u0441 \u043A API \u041C\u0435\u0442\u0440\u0438\u043A\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0441\u044F \u0441\u043E \u0441\u0442\u0430\u0442\u0443\u0441\u043E\u043C ${status}`;
1398
+ const options = { status, errorType, details, requestUrl };
1399
+ const full = `${message} (${errorType}, HTTP ${status})`;
1400
+ if (status === 429 || errorType.startsWith("quota_")) {
1401
+ return new QuotaError(full, {
1402
+ ...options,
1403
+ retryAfterMs: QUOTA_RETRY_MS[errorType] ?? 6e4
1404
+ });
1405
+ }
1406
+ if (status === 401 || status === 403 || AUTH_TYPES.has(errorType)) {
1407
+ return new AuthError(full, options);
1408
+ }
1409
+ if (status === 404 || errorType === "not_found") return new NotFoundError(full, options);
1410
+ if (status >= 500 || SERVER_TYPES.has(errorType)) return new ServerError(full, options);
1411
+ return new InvalidRequestError(full, options);
1412
+ }
1413
+ function isRetryable(error) {
1414
+ return error instanceof QuotaError || error instanceof ServerError;
1415
+ }
1416
+
1417
+ // src/client/rateLimit.ts
1418
+ var SECOND = 1e3;
1419
+ var FIVE_MINUTES = 5 * 60 * 1e3;
1420
+ var defaultSleep = (ms) => new Promise((resolve) => {
1421
+ setTimeout(resolve, ms);
1422
+ });
1423
+ function gmtDay(timestamp) {
1424
+ return Math.floor(timestamp / 864e5);
1425
+ }
1426
+ function prune(timestamps, now, windowMs) {
1427
+ const cutoff = now - windowMs;
1428
+ let drop = 0;
1429
+ while (drop < timestamps.length && timestamps[drop] <= cutoff) drop += 1;
1430
+ if (drop > 0) timestamps.splice(0, drop);
1431
+ }
1432
+ var RateLimiter = class {
1433
+ maxConcurrent;
1434
+ perSecond;
1435
+ reportsPer5Min;
1436
+ perDay;
1437
+ now;
1438
+ sleep;
1439
+ inFlight = 0;
1440
+ secondWindow = [];
1441
+ reportWindow = [];
1442
+ dayKey = -1;
1443
+ dayCount = 0;
1444
+ /** Очередь ожидающих: разбуженные проверяют условия заново. */
1445
+ waiters = [];
1446
+ constructor(options = {}) {
1447
+ this.maxConcurrent = options.maxConcurrent ?? 3;
1448
+ this.perSecond = options.perSecond ?? 30;
1449
+ this.reportsPer5Min = options.reportsPer5Min ?? 200;
1450
+ this.perDay = options.perDay ?? 5e3;
1451
+ this.now = options.now ?? Date.now;
1452
+ this.sleep = options.sleep ?? defaultSleep;
1453
+ }
1454
+ /** Выполняет `fn`, не нарушая квот. Возвращает результат `fn`. */
1455
+ async schedule(scope, fn) {
1456
+ await this.acquire(scope);
1457
+ try {
1458
+ return await fn();
1459
+ } finally {
1460
+ this.release();
1461
+ }
1462
+ }
1463
+ /** Сколько запросов уже израсходовано в текущих окнах — для диагностики. */
1464
+ usage() {
1465
+ const now = this.now();
1466
+ prune(this.secondWindow, now, SECOND);
1467
+ prune(this.reportWindow, now, FIVE_MINUTES);
1468
+ this.rollDay(now);
1469
+ return {
1470
+ inFlight: this.inFlight,
1471
+ lastSecond: this.secondWindow.length,
1472
+ reportsLast5Min: this.reportWindow.length,
1473
+ today: this.dayCount
1474
+ };
1475
+ }
1476
+ rollDay(now) {
1477
+ const key = gmtDay(now);
1478
+ if (key !== this.dayKey) {
1479
+ this.dayKey = key;
1480
+ this.dayCount = 0;
1481
+ }
1482
+ }
1483
+ async acquire(scope) {
1484
+ for (; ; ) {
1485
+ const now = this.now();
1486
+ prune(this.secondWindow, now, SECOND);
1487
+ prune(this.reportWindow, now, FIVE_MINUTES);
1488
+ this.rollDay(now);
1489
+ const wait = this.waitMs(scope, now);
1490
+ if (wait === 0) {
1491
+ this.inFlight += 1;
1492
+ this.secondWindow.push(now);
1493
+ this.dayCount += 1;
1494
+ if (scope === "report") this.reportWindow.push(now);
1495
+ return;
1496
+ }
1497
+ if (this.inFlight > 0 && wait === Number.POSITIVE_INFINITY) {
1498
+ await new Promise((resolve) => this.waiters.push(resolve));
1499
+ continue;
1500
+ }
1501
+ await this.sleep(Math.min(wait, FIVE_MINUTES));
1502
+ }
1503
+ }
1504
+ /** 0 — можно выполнять; Infinity — ждать освобождения слота параллелизма. */
1505
+ waitMs(scope, now) {
1506
+ if (this.dayCount >= this.perDay) {
1507
+ const nextDayStart = (gmtDay(now) + 1) * 864e5;
1508
+ return nextDayStart - now;
1509
+ }
1510
+ if (this.secondWindow.length >= this.perSecond) {
1511
+ return this.secondWindow[0] + SECOND - now;
1512
+ }
1513
+ if (scope === "report" && this.reportWindow.length >= this.reportsPer5Min) {
1514
+ return this.reportWindow[0] + FIVE_MINUTES - now;
1515
+ }
1516
+ if (this.inFlight >= this.maxConcurrent) return Number.POSITIVE_INFINITY;
1517
+ return 0;
1518
+ }
1519
+ release() {
1520
+ this.inFlight -= 1;
1521
+ this.waiters.shift()?.();
1522
+ }
1523
+ };
1524
+
1525
+ // src/client/warnings.ts
1526
+ var consoleWarningHandler = (warning) => {
1527
+ console.warn(`[yandex-metric-parser-lib] ${warning.code}: ${warning.message}`);
1528
+ };
1529
+
1530
+ // src/client/http.ts
1531
+ var DEFAULT_BASE_URL = "https://api-metrika.yandex.net";
1532
+ var sleep = (ms) => new Promise((resolve) => {
1533
+ setTimeout(resolve, ms);
1534
+ });
1535
+ function combineSignals(signals) {
1536
+ const controller = new AbortController();
1537
+ const detach = [];
1538
+ for (const source of signals) {
1539
+ if (source.aborted) {
1540
+ controller.abort(source.reason);
1541
+ break;
1542
+ }
1543
+ const onAbort = () => controller.abort(source.reason);
1544
+ source.addEventListener("abort", onAbort, { once: true });
1545
+ detach.push(() => source.removeEventListener("abort", onAbort));
1546
+ }
1547
+ return {
1548
+ signal: controller.signal,
1549
+ release: () => {
1550
+ for (const off of detach) off();
1551
+ }
1552
+ };
1553
+ }
1554
+ function serialize(value) {
1555
+ return Array.isArray(value) ? value.join(",") : String(value);
1556
+ }
1557
+ function buildUrl(baseUrl, path, query = {}) {
1558
+ const url = new URL(path, baseUrl);
1559
+ for (const [key, value] of Object.entries(query)) {
1560
+ if (value === void 0) continue;
1561
+ url.searchParams.set(key, serialize(value));
1562
+ }
1563
+ return url.toString();
1564
+ }
1565
+ var MetrikaHttpClient = class {
1566
+ lang;
1567
+ warn;
1568
+ limiter;
1569
+ token;
1570
+ baseUrl;
1571
+ fetchImpl;
1572
+ maxRetries;
1573
+ maxRetryDelayMs;
1574
+ timeoutMs;
1575
+ constructor(options) {
1576
+ if (!options.token) throw new Error("\u041D\u0435 \u043F\u0435\u0440\u0435\u0434\u0430\u043D OAuth-\u0442\u043E\u043A\u0435\u043D \u042F\u043D\u0434\u0435\u043A\u0441 \u041C\u0435\u0442\u0440\u0438\u043A\u0438");
1577
+ this.token = options.token;
1578
+ this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
1579
+ this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);
1580
+ this.maxRetries = options.maxRetries ?? 3;
1581
+ this.maxRetryDelayMs = options.maxRetryDelayMs ?? 3e4;
1582
+ this.timeoutMs = options.timeoutMs ?? 6e4;
1583
+ this.lang = options.lang ?? "ru";
1584
+ this.warn = options.onWarning ?? consoleWarningHandler;
1585
+ this.limiter = options.rateLimit instanceof RateLimiter ? options.rateLimit : new RateLimiter(options.rateLimit);
1586
+ }
1587
+ /** Выполняет GET-запрос и разбирает JSON-ответ. */
1588
+ async get(options) {
1589
+ const url = buildUrl(this.baseUrl, options.path, options.query);
1590
+ let lastError;
1591
+ for (let attempt = 0; attempt <= this.maxRetries; attempt += 1) {
1592
+ try {
1593
+ return await this.limiter.schedule(options.scope, () => this.send(url, options.signal));
1594
+ } catch (error) {
1595
+ lastError = error;
1596
+ if (!isRetryable(error) || attempt === this.maxRetries) throw error;
1597
+ const delay = this.retryDelay(error, attempt);
1598
+ if (delay === void 0) throw error;
1599
+ await sleep(delay);
1600
+ }
1601
+ }
1602
+ throw lastError;
1603
+ }
1604
+ /**
1605
+ * Пауза перед повтором. `undefined` — ждать пришлось бы дольше `maxRetryDelayMs`,
1606
+ * повтор бессмыслен и ошибку надо отдать вызывающему коду.
1607
+ */
1608
+ retryDelay(error, attempt) {
1609
+ const required = error.retryAfterMs;
1610
+ const backoff = Math.min(1e3 * 2 ** attempt, this.maxRetryDelayMs);
1611
+ const delay = required ?? backoff;
1612
+ return delay > this.maxRetryDelayMs ? void 0 : delay;
1613
+ }
1614
+ async send(url, signal) {
1615
+ const timeout = AbortSignal.timeout(this.timeoutMs);
1616
+ const combined = combineSignals(signal ? [signal, timeout] : [timeout]);
1617
+ let response;
1618
+ try {
1619
+ response = await this.fetchImpl(url, {
1620
+ method: "GET",
1621
+ headers: {
1622
+ Authorization: `OAuth ${this.token}`,
1623
+ Accept: "application/json",
1624
+ "User-Agent": `yandex-metric-parser-lib (contract ${contractVersion})`
1625
+ },
1626
+ signal: combined.signal
1627
+ });
1628
+ } finally {
1629
+ combined.release();
1630
+ }
1631
+ const text2 = await response.text();
1632
+ const body = text2 ? safeJson(text2) : void 0;
1633
+ if (!response.ok) {
1634
+ throw toMetrikaError(response.status, body, url);
1635
+ }
1636
+ return body;
1637
+ }
1638
+ };
1639
+ function safeJson(text2) {
1640
+ try {
1641
+ return JSON.parse(text2);
1642
+ } catch {
1643
+ return { message: text2.slice(0, 500) };
1644
+ }
1645
+ }
1646
+
1647
+ // src/management/api.ts
1648
+ var CounterLookupError = class extends Error {
1649
+ candidates;
1650
+ constructor(message, candidates) {
1651
+ super(message);
1652
+ this.name = "CounterLookupError";
1653
+ this.candidates = candidates;
1654
+ }
1655
+ };
1656
+ var ManagementApi = class {
1657
+ constructor(http) {
1658
+ this.http = http;
1659
+ }
1660
+ http;
1661
+ /** Счётчики, доступные владельцу токена. */
1662
+ async getCounters(options = {}) {
1663
+ const response = await this.http.get({
1664
+ path: "/management/v1/counters",
1665
+ query: {
1666
+ search_string: options.searchString,
1667
+ permission: options.permission?.length ? options.permission : void 0,
1668
+ per_page: options.perPage,
1669
+ offset: options.offset,
1670
+ // Адрес сайта и зеркала приходят и без field, но просим явно.
1671
+ field: "mirrors"
1672
+ },
1673
+ scope: "management",
1674
+ signal: options.signal
1675
+ });
1676
+ return (response.counters ?? []).map(toCounterBrief);
1677
+ }
1678
+ /**
1679
+ * Находит единственный счётчик по адресу сайта.
1680
+ * Бросает `CounterLookupError` со списком кандидатов, если совпадений нет или их несколько:
1681
+ * запускать выгрузку по наугад выбранному счётчику хуже, чем остановиться.
1682
+ */
1683
+ async findCounterBySite(site, signal) {
1684
+ const needle = normalizeHost(site);
1685
+ const counters = await this.getCounters({
1686
+ searchString: needle,
1687
+ ...signal ? { signal } : {}
1688
+ });
1689
+ const exact = counters.filter(
1690
+ (counter) => normalizeHost(counter.site) === needle || counter.mirrors.some((mirror) => normalizeHost(mirror) === needle)
1691
+ );
1692
+ const matches = exact.length > 0 ? exact : counters;
1693
+ if (matches.length === 1) return matches[0];
1694
+ if (matches.length === 0) {
1695
+ throw new CounterLookupError(
1696
+ `\u0421\u0447\u0451\u0442\u0447\u0438\u043A \u0434\u043B\u044F \u0441\u0430\u0439\u0442\u0430 "${site}" \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D. \u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435, \u0447\u0442\u043E \u0443 \u0430\u043A\u043A\u0430\u0443\u043D\u0442\u0430, \u043D\u0430 \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0432\u044B\u0434\u0430\u043D \u0442\u043E\u043A\u0435\u043D, \u0435\u0441\u0442\u044C \u0434\u043E\u0441\u0442\u0443\u043F \u043A \u044D\u0442\u043E\u043C\u0443 \u0441\u0447\u0451\u0442\u0447\u0438\u043A\u0443.`,
1697
+ []
1698
+ );
1699
+ }
1700
+ throw new CounterLookupError(
1701
+ `\u0421\u0430\u0439\u0442\u0443 "${site}" \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0447\u0451\u0442\u0447\u0438\u043A\u043E\u0432: ${matches.map((counter) => `${counter.id} (${counter.site})`).join(", ")}. \u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u044F\u0432\u043D\u043E.`,
1702
+ matches
1703
+ );
1704
+ }
1705
+ /** Клиенты Директа, доступные указанным счётчикам. */
1706
+ async getDirectClients(counterIds, signal) {
1707
+ const counters = Array.isArray(counterIds) ? counterIds : [counterIds];
1708
+ const response = await this.http.get({
1709
+ path: "/management/v1/clients",
1710
+ query: { counters },
1711
+ scope: "management",
1712
+ signal
1713
+ });
1714
+ return response.clients ?? [];
1715
+ }
1716
+ /** Логины для параметра `direct_client_logins`. */
1717
+ async getDirectClientLogins(counterIds, signal) {
1718
+ const clients = await this.getDirectClients(counterIds, signal);
1719
+ return [...new Set(clients.map((client) => client.chief_login).filter(Boolean))];
1720
+ }
1721
+ };
1722
+ function toCounterBrief(raw) {
1723
+ return {
1724
+ id: raw.id,
1725
+ name: raw.name ?? "",
1726
+ site: raw.site2?.site ?? "",
1727
+ mirrors: (raw.mirrors2 ?? []).map((mirror) => typeof mirror === "string" ? mirror : mirror?.site).filter((site) => Boolean(site)),
1728
+ ...raw.status ? { status: raw.status } : {},
1729
+ ...raw.permission ? { permission: raw.permission } : {},
1730
+ ...raw.owner_login ? { ownerLogin: raw.owner_login } : {}
1731
+ };
1732
+ }
1733
+ function normalizeHost(site) {
1734
+ return site.trim().toLowerCase().replace(/^https?:\/\//, "").replace(/^www\./, "").replace(/\/+$/, "");
1735
+ }
1736
+
1737
+ // src/reports/dates.ts
1738
+ var SETTLED_LAG_DAYS = 3;
1739
+ function settledRange(days = 30, lagDays = SETTLED_LAG_DAYS) {
1740
+ if (days < 1) throw new RangeError("\u041F\u0435\u0440\u0438\u043E\u0434 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435 \u043C\u0435\u043D\u044C\u0448\u0435 \u043E\u0434\u043D\u043E\u0433\u043E \u0434\u043D\u044F");
1741
+ return {
1742
+ date1: `${lagDays + days - 1}daysAgo`,
1743
+ date2: `${lagDays}daysAgo`
1744
+ };
1745
+ }
1746
+
1747
+ // src/reports/validate.ts
1748
+ var LIMITS = {
1749
+ maxDimensions: 10,
1750
+ maxMetrics: 20,
1751
+ maxRowsPerRequest: 1e5,
1752
+ maxFilterLength: 1e4,
1753
+ maxFilterValues: 100
1754
+ };
1755
+ function namespaces(ids) {
1756
+ const result = /* @__PURE__ */ new Set();
1757
+ for (const id2 of ids) {
1758
+ const ns = namespaceOf(id2);
1759
+ if (ns) result.add(ns);
1760
+ }
1761
+ return result;
1762
+ }
1763
+ var ATTRIBUTION_PREFIXES = [
1764
+ "crossDeviceLastSignificant",
1765
+ "crossDeviceFirst",
1766
+ "lastYandexDirectClick",
1767
+ "lastSignificant",
1768
+ "automatic",
1769
+ "first",
1770
+ "last"
1771
+ ];
1772
+ function toContractForm(id2) {
1773
+ const match = /^(ym:[a-z]{1,3}:)(.*)$/.exec(id2);
1774
+ if (!match) return id2;
1775
+ const [, prefix, rest] = match;
1776
+ let tail = rest;
1777
+ for (const attribution of ATTRIBUTION_PREFIXES) {
1778
+ if (tail.startsWith(attribution) && /^[A-Z]/.test(tail.slice(attribution.length))) {
1779
+ tail = `<attribution>${tail.slice(attribution.length)}`;
1780
+ break;
1781
+ }
1782
+ }
1783
+ tail = tail.replace(/\b(RUB|USD|EUR|YND)/g, "<currency>").replace(/goal\d+/g, "goal<goal_id>").replace(/experimentAB\d+/g, "experimentAB<experiment_ab>").replace(/datePeriod(day|week|month|quarter|year)/g, "datePeriod<group>");
1784
+ return `${prefix}${tail}`;
1785
+ }
1786
+ function validateQuery(query, options = {}) {
1787
+ const warnings = [];
1788
+ const dimensions = query.dimensions ?? [];
1789
+ const metrics = query.metrics ?? [];
1790
+ if (!query.preset && metrics.length === 0) {
1791
+ throw new RequestValidationError(
1792
+ "\u041D\u0443\u0436\u043D\u043E \u0443\u043A\u0430\u0437\u0430\u0442\u044C \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u043D\u0443 \u043C\u0435\u0442\u0440\u0438\u043A\u0443 (metrics) \u0438\u043B\u0438 \u0448\u0430\u0431\u043B\u043E\u043D \u043E\u0442\u0447\u0451\u0442\u0430 (preset)"
1793
+ );
1794
+ }
1795
+ if (dimensions.length > LIMITS.maxDimensions) {
1796
+ throw new RequestValidationError(
1797
+ `\u0413\u0440\u0443\u043F\u043F\u0438\u0440\u043E\u0432\u043E\u043A \u0432 \u0437\u0430\u043F\u0440\u043E\u0441\u0435: ${dimensions.length}, \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C ${LIMITS.maxDimensions}`
1798
+ );
1799
+ }
1800
+ if (metrics.length > LIMITS.maxMetrics) {
1801
+ throw new RequestValidationError(
1802
+ `\u041C\u0435\u0442\u0440\u0438\u043A \u0432 \u0437\u0430\u043F\u0440\u043E\u0441\u0435: ${metrics.length}, \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C ${LIMITS.maxMetrics}`
1803
+ );
1804
+ }
1805
+ if (query.limit !== void 0 && (query.limit < 1 || query.limit > LIMITS.maxRowsPerRequest)) {
1806
+ throw new RequestValidationError(
1807
+ `limit \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0432 \u0434\u0438\u0430\u043F\u0430\u0437\u043E\u043D\u0435 1\u2026${LIMITS.maxRowsPerRequest}, \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E ${query.limit}`
1808
+ );
1809
+ }
1810
+ if (query.offset !== void 0 && query.offset < 1) {
1811
+ throw new RequestValidationError(`offset \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442\u0441\u044F \u0441 1, \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E ${query.offset}`);
1812
+ }
1813
+ if (query.filters && query.filters.length > LIMITS.maxFilterLength) {
1814
+ throw new RequestValidationError(
1815
+ `\u0414\u043B\u0438\u043D\u0430 filters ${query.filters.length} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432, \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C ${LIMITS.maxFilterLength}`
1816
+ );
1817
+ }
1818
+ const used = namespaces([...dimensions, ...metrics]);
1819
+ if (used.size > 1) {
1820
+ throw new RequestValidationError(
1821
+ `\u041D\u0435\u043B\u044C\u0437\u044F \u0441\u043C\u0435\u0448\u0438\u0432\u0430\u0442\u044C \u043F\u0440\u043E\u0441\u0442\u0440\u0430\u043D\u0441\u0442\u0432\u0430 \u0438\u043C\u0451\u043D \u0432 \u043E\u0434\u043D\u043E\u043C \u0437\u0430\u043F\u0440\u043E\u0441\u0435: ${[...used].map((ns) => `ym:${ns}:`).join(", ")}. \u0420\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u0435 \u043D\u0430 \u0434\u0432\u0430 \u0437\u0430\u043F\u0440\u043E\u0441\u0430 (\u0441\u043C\u0435\u0448\u0438\u0432\u0430\u0442\u044C \u043C\u043E\u0436\u043D\u043E \u0442\u043E\u043B\u044C\u043A\u043E \u0432 filters).`
1822
+ );
1823
+ }
1824
+ if (used.has("ad") && !query.directClientLogins?.length) {
1825
+ throw new RequestValidationError(
1826
+ "\u0414\u043B\u044F \u043E\u0442\u0447\u0451\u0442\u043E\u0432 ym:ad: \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u0435\u043D \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 directClientLogins. \u041B\u043E\u0433\u0438\u043D\u044B \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0445 \u043A\u043B\u0438\u0435\u043D\u0442\u043E\u0432: GET /management/v1/clients?counters=<id>"
1827
+ );
1828
+ }
1829
+ if (query.preset && !hasPreset(query.preset)) {
1830
+ reportUnknown(`\u0448\u0430\u0431\u043B\u043E\u043D "${query.preset}"`, options, warnings, { preset: query.preset });
1831
+ }
1832
+ for (const id2 of dimensions) {
1833
+ if (!hasDimension(toContractForm(id2))) {
1834
+ reportUnknown(`\u0433\u0440\u0443\u043F\u043F\u0438\u0440\u043E\u0432\u043A\u0430 "${id2}"`, options, warnings, { dimension: id2 });
1835
+ }
1836
+ }
1837
+ for (const id2 of metrics) {
1838
+ if (!hasMetric(toContractForm(id2))) {
1839
+ reportUnknown(`\u043C\u0435\u0442\u0440\u0438\u043A\u0430 "${id2}"`, options, warnings, { metric: id2 });
1840
+ }
1841
+ }
1842
+ if (query.attribution && query.attribution in DEPRECATED_ATTRIBUTIONS) {
1843
+ const replacement = DEPRECATED_ATTRIBUTIONS[query.attribution];
1844
+ warnings.push({
1845
+ code: "deprecated_attribution",
1846
+ message: `\u041C\u043E\u0434\u0435\u043B\u044C \u0430\u0442\u0440\u0438\u0431\u0443\u0446\u0438\u0438 "${query.attribution}" \u0443\u0441\u0442\u0430\u0440\u0435\u043B\u0430: \u0441 25 \u0438\u044E\u043D\u044F 2026 \u0433\u043E\u0434\u0430 API \u0431\u0443\u0434\u0435\u0442 \u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044C \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043F\u043E \u043C\u043E\u0434\u0435\u043B\u0438 "${replacement}". \u041F\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043D\u0430 \u043D\u0435\u0451 \u0437\u0430\u0440\u0430\u043D\u0435\u0435.`,
1847
+ details: { requested: query.attribution, replacement }
1848
+ });
1849
+ }
1850
+ return { warnings };
1851
+ }
1852
+ function reportUnknown(what, options, warnings, details) {
1853
+ const message = `\u041D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430\u044F ${what} \u2014 \u0435\u0451 \u043D\u0435\u0442 \u0432 \u0441\u043D\u0430\u043F\u0448\u043E\u0442\u0435 \u043A\u043E\u043D\u0442\u0440\u0430\u043A\u0442\u0430. \u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u043D\u0430\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u0438\u043B\u0438 \u043E\u0431\u043D\u043E\u0432\u0438\u0442\u0435 \u0441\u043D\u0430\u043F\u0448\u043E\u0442: npm run fetch-docs && npm run parse-contract`;
1854
+ if (options.allowUnknownFields) {
1855
+ warnings.push({ code: "unknown_field", message, details });
1856
+ return;
1857
+ }
1858
+ throw new RequestValidationError(message);
1859
+ }
1860
+
1861
+ // src/reports/data.ts
1862
+ var DEFAULT_PAGE_SIZE = LIMITS.maxRowsPerRequest;
1863
+ function toQueryParams(query, lang) {
1864
+ const range = { date1: query.date1, date2: query.date2 };
1865
+ return {
1866
+ ids: Array.isArray(query.ids) ? query.ids : [query.ids],
1867
+ metrics: query.metrics.length ? query.metrics : void 0,
1868
+ dimensions: query.dimensions?.length ? query.dimensions : void 0,
1869
+ preset: query.preset,
1870
+ date1: range.date1,
1871
+ date2: range.date2,
1872
+ filters: query.filters,
1873
+ sort: query.sort?.length ? query.sort : void 0,
1874
+ // Без full редкие фразы выпадают из выборки — именно они и составляют длинный хвост.
1875
+ accuracy: query.accuracy ?? "full",
1876
+ proposed_accuracy: query.proposedAccuracy,
1877
+ limit: query.limit,
1878
+ offset: query.offset,
1879
+ attribution: query.attribution,
1880
+ currency: query.currency,
1881
+ goal_id: query.goalId,
1882
+ direct_client_logins: query.directClientLogins?.length ? query.directClientLogins : void 0,
1883
+ include_undefined: query.includeUndefined,
1884
+ timezone: query.timezone,
1885
+ lang: query.lang ?? lang
1886
+ };
1887
+ }
1888
+ function inspectResponse(response) {
1889
+ const warnings = [];
1890
+ if (response.sampled) {
1891
+ warnings.push({
1892
+ code: "sampling",
1893
+ message: `\u041E\u0442\u0447\u0451\u0442 \u043F\u043E\u0441\u0442\u0440\u043E\u0435\u043D \u043F\u043E \u0432\u044B\u0431\u043E\u0440\u043A\u0435 ${formatShare(response.sample_share)} \u0434\u0430\u043D\u043D\u044B\u0445 (${response.sample_size ?? "?"} \u0438\u0437 ${response.sample_space ?? "?"} \u0441\u0442\u0440\u043E\u043A). \u0420\u0435\u0434\u043A\u0438\u0435 \u0444\u0440\u0430\u0437\u044B \u043C\u043E\u0433\u043B\u0438 \u043D\u0435 \u043F\u043E\u043F\u0430\u0441\u0442\u044C \u0432 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442.`,
1894
+ details: {
1895
+ sampleShare: response.sample_share,
1896
+ sampleSize: response.sample_size,
1897
+ sampleSpace: response.sample_space
1898
+ }
1899
+ });
1900
+ }
1901
+ if (response.contains_sensitive_data) {
1902
+ warnings.push({
1903
+ code: "sensitive_data_hidden",
1904
+ message: "\u0412 \u043E\u0442\u0432\u0435\u0442\u0435 \u043C\u043E\u0433\u0443\u0442 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043E\u0432\u0430\u0442\u044C \u0441\u0442\u0440\u043E\u043A\u0438, \u043F\u043E \u043A\u043E\u0442\u043E\u0440\u044B\u043C \u0432\u044B\u0431\u043E\u0440\u043A\u0430 \u043C\u0435\u043D\u044C\u0448\u0435 10 \u043F\u043E\u0441\u0435\u0442\u0438\u0442\u0435\u043B\u0435\u0439: \u043F\u043E\u0438\u0441\u043A\u043E\u0432\u044B\u0435 \u0444\u0440\u0430\u0437\u044B \u043E\u0442\u043D\u043E\u0441\u044F\u0442\u0441\u044F \u043A \u043A\u043E\u043D\u0444\u0438\u0434\u0435\u043D\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u043C \u0434\u0430\u043D\u043D\u044B\u043C. \u042D\u0442\u043E \u0440\u0435\u0436\u0435\u0442 \u0434\u043B\u0438\u043D\u043D\u044B\u0439 \u0445\u0432\u043E\u0441\u0442 \u0437\u0430\u043F\u0440\u043E\u0441\u043E\u0432."
1905
+ });
1906
+ }
1907
+ if (response.data_lag && response.data_lag > 0) {
1908
+ warnings.push({
1909
+ code: "data_lag",
1910
+ message: `\u0417\u0430\u0434\u0435\u0440\u0436\u043A\u0430 \u0434\u0430\u043D\u043D\u044B\u0445 ${Math.round(response.data_lag / 60)} \u043C\u0438\u043D \u2014 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u0434\u043D\u0438 \u043F\u0435\u0440\u0438\u043E\u0434\u0430 \u043C\u043E\u0433\u0443\u0442 \u0431\u044B\u0442\u044C \u043D\u0435\u043F\u043E\u043B\u043D\u044B\u043C\u0438.`,
1911
+ details: { dataLagSeconds: response.data_lag }
1912
+ });
1913
+ }
1914
+ for (const id2 of response.query?.dimensions ?? []) {
1915
+ if (!hasDimension(toContractForm(id2))) {
1916
+ warnings.push({
1917
+ code: "unknown_field",
1918
+ message: `API \u0432\u0435\u0440\u043D\u0443\u043B \u0433\u0440\u0443\u043F\u043F\u0438\u0440\u043E\u0432\u043A\u0443 "${id2}", \u043A\u043E\u0442\u043E\u0440\u043E\u0439 \u043D\u0435\u0442 \u0432 \u0441\u043D\u0430\u043F\u0448\u043E\u0442\u0435 \u043A\u043E\u043D\u0442\u0440\u0430\u043A\u0442\u0430 ${contractVersion}.`,
1919
+ details: { dimension: id2 }
1920
+ });
1921
+ }
1922
+ }
1923
+ for (const id2 of response.query?.metrics ?? []) {
1924
+ if (!hasMetric(toContractForm(id2))) {
1925
+ warnings.push({
1926
+ code: "unknown_field",
1927
+ message: `API \u0432\u0435\u0440\u043D\u0443\u043B \u043C\u0435\u0442\u0440\u0438\u043A\u0443 "${id2}", \u043A\u043E\u0442\u043E\u0440\u043E\u0439 \u043D\u0435\u0442 \u0432 \u0441\u043D\u0430\u043F\u0448\u043E\u0442\u0435 \u043A\u043E\u043D\u0442\u0440\u0430\u043A\u0442\u0430 ${contractVersion}.`,
1928
+ details: { metric: id2 }
1929
+ });
1930
+ }
1931
+ }
1932
+ return warnings;
1933
+ }
1934
+ function formatShare(share) {
1935
+ return share === void 0 ? "?" : `${Math.round(share * 100)}%`;
1936
+ }
1937
+ var ReportsApi = class {
1938
+ constructor(http, options = {}) {
1939
+ this.http = http;
1940
+ this.options = options;
1941
+ }
1942
+ http;
1943
+ options;
1944
+ /** Одна страница отчёта. Сырой ответ API без постобработки. */
1945
+ async fetchPage(query, signal) {
1946
+ const { warnings } = validateQuery(query, this.options);
1947
+ warnings.forEach(this.http.warn);
1948
+ return this.http.get({
1949
+ path: "/stat/v1/data",
1950
+ query: toQueryParams(query, this.http.lang),
1951
+ scope: "report",
1952
+ signal
1953
+ });
1954
+ }
1955
+ /**
1956
+ * Выгружает отчёт целиком, постранично по `total_rows`.
1957
+ * Период по умолчанию — 30 дней, заканчивающихся на T-3 (данные визитов дозаполняются ~3 дня).
1958
+ */
1959
+ async fetchAll(query, options = {}) {
1960
+ const pageSize = Math.min(options.pageSize ?? DEFAULT_PAGE_SIZE, LIMITS.maxRowsPerRequest);
1961
+ const defaults = settledRange(30);
1962
+ const base = {
1963
+ ...query,
1964
+ date1: query.date1 ?? defaults.date1,
1965
+ date2: query.date2 ?? defaults.date2
1966
+ };
1967
+ const { warnings: queryWarnings } = validateQuery(base, this.options);
1968
+ const warnings = [...queryWarnings];
1969
+ warnings.forEach(this.http.warn);
1970
+ const rows = [];
1971
+ let offset = base.offset ?? 1;
1972
+ let requests = 0;
1973
+ let totalRows = 0;
1974
+ let meta;
1975
+ for (; ; ) {
1976
+ const remaining = options.maxRows === void 0 ? pageSize : options.maxRows - rows.length;
1977
+ if (remaining <= 0) break;
1978
+ const page = await this.http.get({
1979
+ path: "/stat/v1/data",
1980
+ query: toQueryParams(
1981
+ { ...base, limit: Math.min(pageSize, remaining), offset },
1982
+ this.http.lang
1983
+ ),
1984
+ scope: "report",
1985
+ signal: options.signal
1986
+ });
1987
+ requests += 1;
1988
+ meta ??= page;
1989
+ totalRows = page.total_rows;
1990
+ if (requests === 1) {
1991
+ for (const warning of inspectResponse(page)) {
1992
+ warnings.push(warning);
1993
+ this.http.warn(warning);
1994
+ }
1995
+ }
1996
+ rows.push(...page.data);
1997
+ offset += page.data.length;
1998
+ if (page.data.length === 0 || offset > totalRows) break;
1999
+ }
2000
+ if (options.maxRows !== void 0 && totalRows > rows.length) {
2001
+ const warning = {
2002
+ code: "truncated",
2003
+ message: `\u0412\u044B\u0433\u0440\u0443\u0436\u0435\u043D\u043E ${rows.length} \u0441\u0442\u0440\u043E\u043A \u0438\u0437 ${totalRows}: \u0441\u0440\u0430\u0431\u043E\u0442\u0430\u043B \u043B\u0438\u043C\u0438\u0442 maxRows.`,
2004
+ details: { fetched: rows.length, totalRows }
2005
+ };
2006
+ warnings.push(warning);
2007
+ this.http.warn(warning);
2008
+ }
2009
+ return { rows, meta: buildMeta(meta, rows.length, requests, warnings) };
2010
+ }
2011
+ /** Ленивая постраничная выгрузка — когда весь отчёт не нужно держать в памяти. */
2012
+ async *stream(query, options = {}) {
2013
+ const pageSize = Math.min(options.pageSize ?? DEFAULT_PAGE_SIZE, LIMITS.maxRowsPerRequest);
2014
+ const defaults = settledRange(30);
2015
+ const base = {
2016
+ ...query,
2017
+ date1: query.date1 ?? defaults.date1,
2018
+ date2: query.date2 ?? defaults.date2
2019
+ };
2020
+ validateQuery(base, this.options).warnings.forEach(this.http.warn);
2021
+ let offset = base.offset ?? 1;
2022
+ let emitted = 0;
2023
+ let first = true;
2024
+ for (; ; ) {
2025
+ const remaining = options.maxRows === void 0 ? pageSize : options.maxRows - emitted;
2026
+ if (remaining <= 0) return;
2027
+ const page = await this.http.get({
2028
+ path: "/stat/v1/data",
2029
+ query: toQueryParams(
2030
+ { ...base, limit: Math.min(pageSize, remaining), offset },
2031
+ this.http.lang
2032
+ ),
2033
+ scope: "report",
2034
+ signal: options.signal
2035
+ });
2036
+ if (first) {
2037
+ inspectResponse(page).forEach(this.http.warn);
2038
+ first = false;
2039
+ }
2040
+ for (const row of page.data) {
2041
+ yield row;
2042
+ emitted += 1;
2043
+ }
2044
+ offset += page.data.length;
2045
+ if (page.data.length === 0 || offset > page.total_rows) return;
2046
+ }
2047
+ }
2048
+ /** Отчёт с разбивкой по времени — для динамики фраз. */
2049
+ async bytime(query, signal) {
2050
+ if (query.topKeys !== void 0 && (query.topKeys < 1 || query.topKeys > 30)) {
2051
+ throw new RangeError(`topKeys \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0432 \u0434\u0438\u0430\u043F\u0430\u0437\u043E\u043D\u0435 1\u202630, \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E ${query.topKeys}`);
2052
+ }
2053
+ const defaults = settledRange(30);
2054
+ const base = {
2055
+ ...query,
2056
+ date1: query.date1 ?? defaults.date1,
2057
+ date2: query.date2 ?? defaults.date2
2058
+ };
2059
+ validateQuery(base, this.options).warnings.forEach(this.http.warn);
2060
+ return this.http.get({
2061
+ path: "/stat/v1/data/bytime",
2062
+ query: {
2063
+ ...toQueryParams(base, this.http.lang),
2064
+ group: base.group ?? "day",
2065
+ top_keys: base.topKeys,
2066
+ row_ids: base.rowIds ? JSON.stringify(base.rowIds) : void 0
2067
+ },
2068
+ scope: "report",
2069
+ signal
2070
+ });
2071
+ }
2072
+ };
2073
+ function buildMeta(response, fetchedRows, requests, warnings) {
2074
+ return {
2075
+ contractVersion,
2076
+ sampled: response?.sampled ?? false,
2077
+ sampleShare: response?.sample_share,
2078
+ sampleSize: response?.sample_size,
2079
+ sampleSpace: response?.sample_space,
2080
+ containsSensitiveData: response?.contains_sensitive_data ?? false,
2081
+ dataLagSeconds: response?.data_lag,
2082
+ totalRows: response?.total_rows ?? fetchedRows,
2083
+ fetchedRows,
2084
+ requests,
2085
+ warnings
2086
+ };
2087
+ }
2088
+
2089
+ // src/keywords/shared.ts
2090
+ var DIM = {
2091
+ searchPhrase: "ym:s:<attribution>SearchPhrase",
2092
+ searchEngineRoot: "ym:s:<attribution>SearchEngineRoot",
2093
+ trafficSource: "ym:s:<attribution>TrafficSource",
2094
+ isRobot: "ym:s:isRobot",
2095
+ startUrl: "ym:s:startURL",
2096
+ visitDirectSearchPhrase: "ym:s:<attribution>DirectSearchPhrase",
2097
+ visitDirectPhraseOrCond: "ym:s:<attribution>DirectPhraseOrCond",
2098
+ adDirectSearchPhrase: "ym:ad:<attribution>DirectSearchPhrase",
2099
+ adDirectPhraseOrCond: "ym:ad:<attribution>DirectPhraseOrCond",
2100
+ adDirectOrder: "ym:ad:<attribution>DirectOrder",
2101
+ adDirectConditionType: "ym:ad:<attribution>DirectConditionType"
2102
+ };
2103
+ var METRIC = {
2104
+ visits: "ym:s:visits",
2105
+ users: "ym:s:users",
2106
+ bounceRate: "ym:s:bounceRate",
2107
+ pageDepth: "ym:s:pageDepth",
2108
+ avgVisitDuration: "ym:s:avgVisitDurationSeconds",
2109
+ anyGoalConversionRate: "ym:s:anyGoalConversionRate",
2110
+ adClicks: "ym:ad:clicks",
2111
+ adVisits: "ym:ad:visits",
2112
+ adUsers: "ym:ad:users",
2113
+ adBounceRate: "ym:ad:bounceRate",
2114
+ adCost: "ym:ad:<currency>ConvertedAdCost",
2115
+ adCostPerVisit: "ym:ad:<currency>ConvertedAdCostPerVisit"
2116
+ };
2117
+ function andFilters(...parts) {
2118
+ const clauses = parts.filter((part) => Boolean(part?.trim()));
2119
+ if (clauses.length === 0) return void 0;
2120
+ return clauses.map((clause) => clauses.length > 1 ? `(${clause})` : clause).join(" AND ");
2121
+ }
2122
+ function text(value) {
2123
+ return value?.name ?? value?.id ?? "";
2124
+ }
2125
+ function id(value) {
2126
+ return value?.id ?? void 0;
2127
+ }
2128
+ function num(row, index) {
2129
+ const value = row.metrics[index];
2130
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
2131
+ }
2132
+ function normalizePhrase(phrase) {
2133
+ return phrase.trim().replace(/\s+/g, " ").toLowerCase().replace(/ё/g, "\u0435");
2134
+ }
2135
+
2136
+ // src/keywords/directCost.ts
2137
+ var METRICS = [
2138
+ METRIC.adClicks,
2139
+ METRIC.adVisits,
2140
+ METRIC.adUsers,
2141
+ METRIC.adCost,
2142
+ METRIC.adCostPerVisit,
2143
+ METRIC.adBounceRate
2144
+ ];
2145
+ async function getDirectSearchPhraseCost(reports, options) {
2146
+ const report = await reports.fetchAll(
2147
+ {
2148
+ ids: options.counterId,
2149
+ dimensions: [
2150
+ DIM.adDirectSearchPhrase,
2151
+ DIM.adDirectPhraseOrCond,
2152
+ DIM.adDirectConditionType,
2153
+ DIM.adDirectOrder
2154
+ ],
2155
+ metrics: METRICS,
2156
+ filters: andFilters(
2157
+ options.conditionTypes?.length ? `${DIM.adDirectConditionType}=.(${options.conditionTypes.map((type) => `'${type}'`).join(",")})` : void 0,
2158
+ options.filters
2159
+ ),
2160
+ attribution: options.attribution ?? "last",
2161
+ currency: options.currency,
2162
+ directClientLogins: options.directClientLogins,
2163
+ date1: options.date1,
2164
+ date2: options.date2,
2165
+ sort: [`-${METRIC.adClicks}`]
2166
+ },
2167
+ { maxRows: options.maxRows, signal: options.signal }
2168
+ );
2169
+ return { rows: report.rows.map(toDirectCostRow), meta: report.meta };
2170
+ }
2171
+ function toDirectCostRow(row) {
2172
+ const conditionType = text(row.dimensions[2]);
2173
+ const campaignId = id(row.dimensions[3]);
2174
+ return {
2175
+ query: text(row.dimensions[0]),
2176
+ keyword: text(row.dimensions[1]),
2177
+ ...conditionType ? { conditionType } : {},
2178
+ ...campaignId ? { campaignId } : {},
2179
+ campaignName: text(row.dimensions[3]),
2180
+ clicks: num(row, 0),
2181
+ visits: num(row, 1),
2182
+ users: num(row, 2),
2183
+ cost: num(row, 3),
2184
+ costPerVisit: num(row, 4),
2185
+ bounceRate: num(row, 5)
2186
+ };
2187
+ }
2188
+
2189
+ // src/keywords/directVisits.ts
2190
+ var METRICS2 = [METRIC.visits, METRIC.users, METRIC.bounceRate, METRIC.anyGoalConversionRate];
2191
+ async function getDirectKeywordsByVisits(reports, options) {
2192
+ const report = await reports.fetchAll(
2193
+ {
2194
+ ids: options.counterId,
2195
+ dimensions: [DIM.visitDirectPhraseOrCond, DIM.visitDirectSearchPhrase],
2196
+ metrics: METRICS2,
2197
+ filters: andFilters(
2198
+ options.excludeRobots === false ? void 0 : `${DIM.isRobot}=='No'`,
2199
+ options.filters
2200
+ ),
2201
+ attribution: options.attribution ?? "last",
2202
+ date1: options.date1,
2203
+ date2: options.date2,
2204
+ sort: [`-${METRIC.visits}`]
2205
+ },
2206
+ { maxRows: options.maxRows, signal: options.signal }
2207
+ );
2208
+ return { rows: report.rows.map(toDirectVisitRow), meta: report.meta };
2209
+ }
2210
+ function toDirectVisitRow(row) {
2211
+ return {
2212
+ keyword: text(row.dimensions[0]),
2213
+ query: text(row.dimensions[1]),
2214
+ visits: num(row, 0),
2215
+ users: num(row, 1),
2216
+ bounceRate: num(row, 2),
2217
+ anyGoalConversionRate: num(row, 3)
2218
+ };
2219
+ }
2220
+
2221
+ // src/keywords/organic.ts
2222
+ function organicFilters(options) {
2223
+ const engines = options.searchEngines?.length ? `${DIM.searchEngineRoot}=.(${options.searchEngines.map((e) => `'${e}'`).join(",")})` : void 0;
2224
+ return andFilters(
2225
+ `${DIM.trafficSource}=='organic'`,
2226
+ options.excludeRobots === false ? void 0 : `${DIM.isRobot}=='No'`,
2227
+ engines,
2228
+ options.filters
2229
+ );
2230
+ }
2231
+ var METRICS3 = [
2232
+ METRIC.visits,
2233
+ METRIC.users,
2234
+ METRIC.bounceRate,
2235
+ METRIC.pageDepth,
2236
+ METRIC.avgVisitDuration
2237
+ ];
2238
+ async function getOrganicSearchPhrases(reports, options) {
2239
+ const report = await reports.fetchAll(
2240
+ {
2241
+ ids: options.counterId,
2242
+ dimensions: [DIM.searchPhrase, DIM.searchEngineRoot],
2243
+ metrics: METRICS3,
2244
+ filters: organicFilters(options),
2245
+ attribution: options.attribution ?? "last",
2246
+ date1: options.date1,
2247
+ date2: options.date2,
2248
+ sort: [`-${METRIC.visits}`]
2249
+ },
2250
+ { maxRows: options.maxRows, signal: options.signal }
2251
+ );
2252
+ return { rows: report.rows.map(toOrganicRow), meta: report.meta };
2253
+ }
2254
+ function toOrganicRow(row) {
2255
+ const engineId = id(row.dimensions[1]);
2256
+ return {
2257
+ phrase: text(row.dimensions[0]),
2258
+ searchEngine: text(row.dimensions[1]),
2259
+ ...engineId ? { searchEngineId: engineId } : {},
2260
+ visits: num(row, 0),
2261
+ users: num(row, 1),
2262
+ bounceRate: num(row, 2),
2263
+ pageDepth: num(row, 3),
2264
+ avgVisitDurationSeconds: num(row, 4)
2265
+ };
2266
+ }
2267
+
2268
+ // src/keywords/landing.ts
2269
+ var METRICS4 = [METRIC.visits, METRIC.users, METRIC.bounceRate, METRIC.avgVisitDuration];
2270
+ async function getPhraseLandingMap(reports, options) {
2271
+ const report = await reports.fetchAll(
2272
+ {
2273
+ ids: options.counterId,
2274
+ dimensions: [DIM.searchPhrase, DIM.startUrl],
2275
+ metrics: METRICS4,
2276
+ filters: organicFilters(options),
2277
+ attribution: options.attribution ?? "last",
2278
+ date1: options.date1,
2279
+ date2: options.date2,
2280
+ sort: [`-${METRIC.visits}`]
2281
+ },
2282
+ { maxRows: options.maxRows, signal: options.signal }
2283
+ );
2284
+ return { rows: report.rows.map(toLandingRow), meta: report.meta };
2285
+ }
2286
+ function toLandingRow(row) {
2287
+ return {
2288
+ phrase: text(row.dimensions[0]),
2289
+ url: text(row.dimensions[1]),
2290
+ visits: num(row, 0),
2291
+ users: num(row, 1),
2292
+ bounceRate: num(row, 2),
2293
+ avgVisitDurationSeconds: num(row, 3)
2294
+ };
2295
+ }
2296
+
2297
+ // src/keywords/timeline.ts
2298
+ var MAX_TIMELINE_ROWS = 30;
2299
+ async function getPhraseTimeline(reports, options) {
2300
+ const topPhrases = Math.min(options.topPhrases ?? 10, MAX_TIMELINE_ROWS);
2301
+ const response = await reports.bytime(
2302
+ {
2303
+ ids: options.counterId,
2304
+ dimensions: [DIM.searchPhrase],
2305
+ metrics: [METRIC.visits],
2306
+ filters: organicFilters(options),
2307
+ attribution: options.attribution ?? "last",
2308
+ date1: options.date1,
2309
+ date2: options.date2,
2310
+ group: options.group ?? "day",
2311
+ ...options.phrases?.length ? { rowIds: options.phrases.map((phrase) => [phrase]) } : { topKeys: topPhrases }
2312
+ },
2313
+ options.signal
2314
+ );
2315
+ const intervals = response.time_intervals ?? [];
2316
+ return response.data.map((row) => toTimeline(row, intervals));
2317
+ }
2318
+ function toTimeline(row, intervals) {
2319
+ const series = row.metrics[0] ?? [];
2320
+ const points = series.map((value, index) => ({
2321
+ from: intervals[index]?.[0] ?? "",
2322
+ to: intervals[index]?.[1] ?? "",
2323
+ visits: typeof value === "number" && Number.isFinite(value) ? value : 0
2324
+ }));
2325
+ return {
2326
+ phrase: text(row.dimensions[0]),
2327
+ points,
2328
+ totalVisits: points.reduce((sum, point) => sum + point.visits, 0),
2329
+ trend: computeTrend(points)
2330
+ };
2331
+ }
2332
+ function computeTrend(points) {
2333
+ if (points.length < 2) return null;
2334
+ const middle = Math.floor(points.length / 2);
2335
+ const sum = (slice) => slice.reduce((total, point) => total + point.visits, 0);
2336
+ const first = sum(points.slice(0, middle));
2337
+ if (first === 0) return null;
2338
+ return sum(points.slice(middle)) / first;
2339
+ }
2340
+
2341
+ // src/keywords/quality.ts
2342
+ var PRIVACY_THRESHOLD_USERS = 10;
2343
+ function qualityOf(meta) {
2344
+ return {
2345
+ sampled: meta.sampled,
2346
+ sensitiveDataHidden: meta.containsSensitiveData,
2347
+ belowPrivacyThreshold: false
2348
+ };
2349
+ }
2350
+ function isBelowPrivacyThreshold(users) {
2351
+ return users > 0 && users < PRIVACY_THRESHOLD_USERS;
2352
+ }
2353
+ function mergeQuality(a, b) {
2354
+ return {
2355
+ sampled: a.sampled || b.sampled,
2356
+ sensitiveDataHidden: a.sensitiveDataHidden || b.sensitiveDataHidden,
2357
+ belowPrivacyThreshold: a.belowPrivacyThreshold || b.belowPrivacyThreshold
2358
+ };
2359
+ }
2360
+ function mergeMeta(entries, belowPrivacyThreshold) {
2361
+ const shares = entries.map(({ meta }) => meta.sampleShare).filter((share) => typeof share === "number");
2362
+ return {
2363
+ contractVersion: entries[0]?.meta.contractVersion ?? "",
2364
+ sampled: entries.some(({ meta }) => meta.sampled),
2365
+ ...shares.length ? { minSampleShare: Math.min(...shares) } : {},
2366
+ containsSensitiveData: entries.some(({ meta }) => meta.containsSensitiveData),
2367
+ belowPrivacyThreshold,
2368
+ requests: entries.reduce((sum, { meta }) => sum + meta.requests, 0),
2369
+ warnings: entries.flatMap(({ meta }) => meta.warnings),
2370
+ sources: entries.map(({ source }) => source)
2371
+ };
2372
+ }
2373
+
2374
+ // src/keywords/merge.ts
2375
+ function mergeKeywords(input) {
2376
+ const index = /* @__PURE__ */ new Map();
2377
+ const metas = [];
2378
+ if (input.organic) {
2379
+ metas.push({ source: "organic", meta: input.organic.meta });
2380
+ for (const row of input.organic.rows) {
2381
+ if (!row.phrase) continue;
2382
+ const entry = ensure(index, row.phrase, input.organic.meta);
2383
+ addSource(entry, "organic");
2384
+ const stats = entry.organic ??= emptyOrganic();
2385
+ stats.visits += row.visits;
2386
+ stats.users += row.users;
2387
+ stats.bounceRate += row.bounceRate * row.visits;
2388
+ stats.pageDepth += row.pageDepth * row.visits;
2389
+ stats.avgVisitDurationSeconds += row.avgVisitDurationSeconds * row.visits;
2390
+ if (row.searchEngine && !stats.searchEngines.includes(row.searchEngine)) {
2391
+ stats.searchEngines.push(row.searchEngine);
2392
+ }
2393
+ }
2394
+ }
2395
+ if (input.directCost) {
2396
+ metas.push({ source: "directCost", meta: input.directCost.meta });
2397
+ for (const row of input.directCost.rows) {
2398
+ if (!row.query) continue;
2399
+ const entry = ensure(index, row.query, input.directCost.meta);
2400
+ addSource(entry, "direct_query");
2401
+ const stats = entry.direct ??= emptyDirect();
2402
+ stats.clicks += row.clicks;
2403
+ stats.visits += row.visits;
2404
+ stats.users += row.users;
2405
+ stats.cost += row.cost;
2406
+ stats.bounceRate += row.bounceRate * row.visits;
2407
+ pushUnique(stats.keywords, row.keyword);
2408
+ pushUnique(stats.campaigns, row.campaignName);
2409
+ }
2410
+ }
2411
+ if (input.directVisits) {
2412
+ metas.push({ source: "directVisits", meta: input.directVisits.meta });
2413
+ for (const row of input.directVisits.rows) {
2414
+ if (!row.query) continue;
2415
+ const entry = ensure(index, row.query, input.directVisits.meta);
2416
+ addSource(entry, "direct_query");
2417
+ const stats = entry.direct ??= emptyDirect();
2418
+ if (stats.visits === 0) {
2419
+ stats.visits = row.visits;
2420
+ stats.users = row.users;
2421
+ stats.bounceRate = row.bounceRate * row.visits;
2422
+ }
2423
+ stats.anyGoalConversionRate = row.anyGoalConversionRate;
2424
+ pushUnique(stats.keywords, row.keyword);
2425
+ }
2426
+ }
2427
+ if (input.landings) {
2428
+ metas.push({ source: "landings", meta: input.landings.meta });
2429
+ for (const row of input.landings.rows) {
2430
+ if (!row.phrase || !row.url) continue;
2431
+ const entry = ensure(index, row.phrase, input.landings.meta);
2432
+ const existing = entry.landings.find((landing) => landing.url === row.url);
2433
+ if (existing) existing.visits += row.visits;
2434
+ else entry.landings.push({ url: row.url, visits: row.visits });
2435
+ }
2436
+ }
2437
+ const keywords = [...index.values()];
2438
+ for (const keyword of keywords) finalize(keyword);
2439
+ keywords.sort((a, b) => b.totalVisits - a.totalVisits || a.phrase.localeCompare(b.phrase));
2440
+ const belowThreshold = keywords.filter((k) => k.quality.belowPrivacyThreshold).length;
2441
+ return { keywords, meta: mergeMeta(metas, belowThreshold) };
2442
+ }
2443
+ function aggregateDirectKeywords(report) {
2444
+ const index = /* @__PURE__ */ new Map();
2445
+ for (const row of report.rows) {
2446
+ if (!row.keyword) continue;
2447
+ const key = normalizePhrase(row.keyword);
2448
+ let entry = index.get(key);
2449
+ if (!entry) {
2450
+ entry = {
2451
+ keyword: row.keyword,
2452
+ clicks: 0,
2453
+ visits: 0,
2454
+ users: 0,
2455
+ cost: 0,
2456
+ queries: [],
2457
+ campaigns: []
2458
+ };
2459
+ index.set(key, entry);
2460
+ }
2461
+ entry.clicks += row.clicks;
2462
+ entry.visits += row.visits;
2463
+ entry.users += row.users;
2464
+ entry.cost += row.cost;
2465
+ pushUnique(entry.queries, row.query);
2466
+ pushUnique(entry.campaigns, row.campaignName);
2467
+ }
2468
+ return [...index.values()].sort((a, b) => b.clicks - a.clicks);
2469
+ }
2470
+ function ensure(index, displayPhrase, meta) {
2471
+ const phrase = normalizePhrase(displayPhrase);
2472
+ let entry = index.get(phrase);
2473
+ if (!entry) {
2474
+ entry = {
2475
+ phrase,
2476
+ displayPhrase,
2477
+ sources: [],
2478
+ landings: [],
2479
+ totalVisits: 0,
2480
+ totalUsers: 0,
2481
+ quality: qualityOf(meta)
2482
+ };
2483
+ index.set(phrase, entry);
2484
+ return entry;
2485
+ }
2486
+ entry.quality = mergeQuality(entry.quality, qualityOf(meta));
2487
+ return entry;
2488
+ }
2489
+ function addSource(entry, source) {
2490
+ if (!entry.sources.includes(source)) entry.sources.push(source);
2491
+ }
2492
+ function pushUnique(list, value) {
2493
+ if (value && !list.includes(value)) list.push(value);
2494
+ }
2495
+ function emptyOrganic() {
2496
+ return {
2497
+ visits: 0,
2498
+ users: 0,
2499
+ bounceRate: 0,
2500
+ pageDepth: 0,
2501
+ avgVisitDurationSeconds: 0,
2502
+ searchEngines: []
2503
+ };
2504
+ }
2505
+ function emptyDirect() {
2506
+ return {
2507
+ clicks: 0,
2508
+ visits: 0,
2509
+ users: 0,
2510
+ cost: 0,
2511
+ costPerVisit: 0,
2512
+ bounceRate: 0,
2513
+ keywords: [],
2514
+ campaigns: []
2515
+ };
2516
+ }
2517
+ function finalize(keyword) {
2518
+ if (keyword.organic && keyword.organic.visits > 0) {
2519
+ const { visits } = keyword.organic;
2520
+ keyword.organic.bounceRate = round(keyword.organic.bounceRate / visits);
2521
+ keyword.organic.pageDepth = round(keyword.organic.pageDepth / visits);
2522
+ keyword.organic.avgVisitDurationSeconds = round(
2523
+ keyword.organic.avgVisitDurationSeconds / visits
2524
+ );
2525
+ }
2526
+ if (keyword.direct) {
2527
+ if (keyword.direct.visits > 0) {
2528
+ keyword.direct.bounceRate = round(keyword.direct.bounceRate / keyword.direct.visits);
2529
+ keyword.direct.costPerVisit = round(keyword.direct.cost / keyword.direct.visits);
2530
+ }
2531
+ keyword.direct.cost = round(keyword.direct.cost);
2532
+ }
2533
+ keyword.landings.sort((a, b) => b.visits - a.visits);
2534
+ keyword.totalVisits = (keyword.organic?.visits ?? 0) + (keyword.direct?.visits ?? 0);
2535
+ keyword.totalUsers = (keyword.organic?.users ?? 0) + (keyword.direct?.users ?? 0);
2536
+ keyword.quality.belowPrivacyThreshold = isBelowPrivacyThreshold(keyword.totalUsers);
2537
+ }
2538
+ function round(value) {
2539
+ return Math.round(value * 100) / 100;
2540
+ }
2541
+
2542
+ // src/metrika.ts
2543
+ var YandexMetrika = class {
2544
+ http;
2545
+ reports;
2546
+ management;
2547
+ constructor(options) {
2548
+ this.http = new MetrikaHttpClient(options);
2549
+ this.reports = new ReportsApi(this.http, {
2550
+ allowUnknownFields: options.allowUnknownFields ?? false
2551
+ });
2552
+ this.management = new ManagementApi(this.http);
2553
+ }
2554
+ /** Версия контракта, по которой собрана библиотека. */
2555
+ contract() {
2556
+ return { version: contractVersion, sourceSha256: contractSourceSha256, parsedAt: contractParsedAt };
2557
+ }
2558
+ /** Рецепт A: поисковые фразы органики. */
2559
+ getOrganicSearchPhrases(options) {
2560
+ return getOrganicSearchPhrases(this.reports, options);
2561
+ }
2562
+ /** Рецепт B: фраза × посадочная страница. */
2563
+ getPhraseLandingMap(options) {
2564
+ return getPhraseLandingMap(this.reports, options);
2565
+ }
2566
+ /**
2567
+ * Рецепт C: запросы Директа с кликами и расходами.
2568
+ * Если `directClientLogins` не передан, логины запрашиваются автоматически.
2569
+ */
2570
+ async getDirectSearchPhraseCost(options) {
2571
+ const logins = options.directClientLogins ?? await this.management.getDirectClientLogins(options.counterId, options.signal);
2572
+ return getDirectSearchPhraseCost(this.reports, { ...options, directClientLogins: logins });
2573
+ }
2574
+ /** Рецепт D: ключевые слова Директа по визитам, без доступа к кампаниям. */
2575
+ getDirectKeywordsByVisits(options) {
2576
+ return getDirectKeywordsByVisits(this.reports, options);
2577
+ }
2578
+ /** Рецепт E: динамика фраз во времени. */
2579
+ getPhraseTimeline(options) {
2580
+ return getPhraseTimeline(this.reports, options);
2581
+ }
2582
+ /**
2583
+ * Сквозной сценарий: выгружает органику, посадочные страницы и Директ,
2584
+ * склеивает в единый реестр ключевых слов.
2585
+ */
2586
+ async buildKeywordRegistry(options) {
2587
+ const organic = await this.getOrganicSearchPhrases(options);
2588
+ const landings = options.withLandings === false ? void 0 : await this.getPhraseLandingMap(options);
2589
+ let directCost;
2590
+ let directVisits;
2591
+ if (options.withDirect !== false) {
2592
+ const logins = options.directClientLogins ?? await this.management.getDirectClientLogins(options.counterId, options.signal).catch(() => []);
2593
+ if (logins.length > 0) {
2594
+ directCost = await getDirectSearchPhraseCost(this.reports, {
2595
+ ...options,
2596
+ directClientLogins: logins
2597
+ });
2598
+ } else {
2599
+ this.http.warn({
2600
+ code: "direct_access_missing",
2601
+ message: "\u041D\u0435\u0442 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0445 \u043B\u043E\u0433\u0438\u043D\u043E\u0432 \u043A\u043B\u0438\u0435\u043D\u0442\u043E\u0432 \u0414\u0438\u0440\u0435\u043A\u0442\u0430 \u2014 \u043A\u043B\u0438\u043A\u0438 \u0438 \u0440\u0430\u0441\u0445\u043E\u0434\u044B \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D\u044B. \u041A\u043B\u044E\u0447\u0435\u0432\u044B\u0435 \u0441\u043B\u043E\u0432\u0430 \u0414\u0438\u0440\u0435\u043A\u0442\u0430 \u0432\u044B\u0433\u0440\u0443\u0436\u0435\u043D\u044B \u043F\u043E \u0432\u0438\u0437\u0438\u0442\u0430\u043C (\u0431\u0435\u0437 \u043A\u043B\u0438\u043A\u043E\u0432 \u0438 \u0434\u0435\u043D\u0435\u0433)."
2602
+ });
2603
+ directVisits = await this.getDirectKeywordsByVisits(options);
2604
+ }
2605
+ }
2606
+ return mergeKeywords({
2607
+ organic,
2608
+ ...landings ? { landings } : {},
2609
+ ...directCost ? { directCost } : {},
2610
+ ...directVisits ? { directVisits } : {}
2611
+ });
2612
+ }
2613
+ };
2614
+
2615
+ // src/contract/used.ts
2616
+ var USED_DIMENSIONS = {
2617
+ "ym:s:<attribution>SearchPhrase": "organic: \u043F\u043E\u0438\u0441\u043A\u043E\u0432\u0430\u044F \u0444\u0440\u0430\u0437\u0430",
2618
+ "ym:s:<attribution>SearchEngineRoot": "organic: \u043F\u043E\u0438\u0441\u043A\u043E\u0432\u0430\u044F \u0441\u0438\u0441\u0442\u0435\u043C\u0430",
2619
+ "ym:s:<attribution>TrafficSource": "organic: \u0444\u0438\u043B\u044C\u0442\u0440 \u043F\u043E \u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A\u0443 \u0442\u0440\u0430\u0444\u0438\u043A\u0430",
2620
+ "ym:s:isRobot": "organic: \u043E\u0442\u0441\u0435\u0447\u043A\u0430 \u0440\u043E\u0431\u043E\u0442\u043E\u0432",
2621
+ "ym:s:startURL": "landing: \u043F\u043E\u0441\u0430\u0434\u043E\u0447\u043D\u0430\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430",
2622
+ "ym:s:<attribution>DirectSearchPhrase": "directVisits: \u0440\u0435\u0430\u043B\u044C\u043D\u044B\u0439 \u0437\u0430\u043F\u0440\u043E\u0441 \u0414\u0438\u0440\u0435\u043A\u0442\u0430",
2623
+ "ym:s:<attribution>DirectPhraseOrCond": "directVisits: \u0443\u0441\u043B\u043E\u0432\u0438\u0435 \u043F\u043E\u043A\u0430\u0437\u0430",
2624
+ "ym:ad:<attribution>DirectSearchPhrase": "directCost: \u0440\u0435\u0430\u043B\u044C\u043D\u044B\u0439 \u0437\u0430\u043F\u0440\u043E\u0441 \u0414\u0438\u0440\u0435\u043A\u0442\u0430",
2625
+ "ym:ad:<attribution>DirectPhraseOrCond": "directCost: \u0443\u0441\u043B\u043E\u0432\u0438\u0435 \u043F\u043E\u043A\u0430\u0437\u0430",
2626
+ "ym:ad:<attribution>DirectOrder": "directCost: \u043A\u0430\u043C\u043F\u0430\u043D\u0438\u044F",
2627
+ "ym:ad:<attribution>DirectConditionType": "directCost: \u0442\u0438\u043F \u0443\u0441\u043B\u043E\u0432\u0438\u044F \u043F\u043E\u043A\u0430\u0437\u0430"
2628
+ };
2629
+ var USED_METRICS = {
2630
+ "ym:s:visits": "organic, directVisits",
2631
+ "ym:s:users": "organic, directVisits",
2632
+ "ym:s:bounceRate": "organic, directVisits",
2633
+ "ym:s:pageDepth": "organic",
2634
+ "ym:s:avgVisitDurationSeconds": "organic, landing",
2635
+ "ym:s:anyGoalConversionRate": "directVisits",
2636
+ "ym:ad:clicks": "directCost: \u043A\u043B\u0438\u043A\u0438 \u043F\u043E \u0440\u0435\u043A\u043B\u0430\u043C\u0435",
2637
+ "ym:ad:visits": "directCost",
2638
+ "ym:ad:users": "directCost",
2639
+ "ym:ad:bounceRate": "directCost",
2640
+ "ym:ad:<currency>ConvertedAdCost": "directCost: \u0440\u0430\u0441\u0445\u043E\u0434\u044B",
2641
+ "ym:ad:<currency>ConvertedAdCostPerVisit": "directCost: \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C \u0432\u0438\u0437\u0438\u0442\u0430"
2642
+ };
2643
+ var USED_PRESETS = {
2644
+ sources_search_phrases: "\u044D\u043A\u0432\u0438\u0432\u0430\u043B\u0435\u043D\u0442 \u0440\u0435\u0446\u0435\u043F\u0442\u0430 organic \u0431\u0435\u0437 \u043E\u0442\u0441\u0435\u0447\u043A\u0438 \u0440\u043E\u0431\u043E\u0442\u043E\u0432",
2645
+ sources_direct_summary: "\u044D\u043A\u0432\u0438\u0432\u0430\u043B\u0435\u043D\u0442 \u0440\u0435\u0446\u0435\u043F\u0442\u0430 directVisits",
2646
+ sources_direct_clicks: "\u044D\u043A\u0432\u0438\u0432\u0430\u043B\u0435\u043D\u0442 \u0440\u0435\u0446\u0435\u043F\u0442\u0430 directCost"
2647
+ };
2648
+ export {
2649
+ AuthError,
2650
+ CounterLookupError,
2651
+ DEFAULT_BASE_URL,
2652
+ DEPRECATED_ATTRIBUTIONS,
2653
+ DIM,
2654
+ DIMENSION_IDS,
2655
+ InvalidRequestError,
2656
+ LIMITS,
2657
+ MAX_TIMELINE_ROWS,
2658
+ METRIC,
2659
+ METRIC_IDS,
2660
+ ManagementApi,
2661
+ MetrikaError,
2662
+ MetrikaHttpClient,
2663
+ NotFoundError,
2664
+ PRESET_IDS,
2665
+ PRIVACY_THRESHOLD_USERS,
2666
+ QuotaError,
2667
+ RateLimiter,
2668
+ ReportsApi,
2669
+ RequestValidationError,
2670
+ SETTLED_LAG_DAYS,
2671
+ ServerError,
2672
+ USED_DIMENSIONS,
2673
+ USED_METRICS,
2674
+ USED_PRESETS,
2675
+ YandexMetrika,
2676
+ aggregateDirectKeywords,
2677
+ andFilters,
2678
+ buildUrl,
2679
+ consoleWarningHandler,
2680
+ contractParsedAt,
2681
+ contractSourceSha256,
2682
+ contractVersion,
2683
+ getDirectKeywordsByVisits,
2684
+ getDirectSearchPhraseCost,
2685
+ getOrganicSearchPhrases,
2686
+ getPhraseLandingMap,
2687
+ getPhraseTimeline,
2688
+ hasDimension,
2689
+ hasMetric,
2690
+ hasPreset,
2691
+ inspectResponse,
2692
+ isBelowPrivacyThreshold,
2693
+ isRetryable,
2694
+ mergeKeywords,
2695
+ mergeMeta,
2696
+ mergeQuality,
2697
+ namespaceOf,
2698
+ normalizePhrase,
2699
+ organicFilters,
2700
+ qualityOf,
2701
+ settledRange,
2702
+ toContractForm,
2703
+ toMetrikaError,
2704
+ toQueryParams,
2705
+ validateQuery
2706
+ };
2707
+ //# sourceMappingURL=index.js.map