1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
|
{
"type": "object",
"required": [
"telemetryId",
"searchPageRegexp",
"queryParamName",
"queryParamNames"
],
"properties": {
"telemetryId": {
"type": "string",
"title": "Telemetry Id",
"description": "The telemetry identifier for the provider.",
"pattern": "^[a-z0-9-._]*$"
},
"searchPageMatches": {
"type": "array",
"title": "Search Page Matches",
"description": "An array containing match expressions used to match on URLs.",
"items": {
"type": "string"
}
},
"searchPageRegexp": {
"type": "string",
"title": "Search Page Regular Expression",
"description": "A regular expression which matches the search page of the provider."
},
"queryParamName": {
"type": "string",
"title": "Search Query Parameter Name",
"description": "The name of the query parameter for the user's search string. This is deprecated, in preference to queryParamNames, but still defined for older clients (pre Firefox 121)."
},
"queryParamNames": {
"type": "array",
"title": "Search Query Parameter Names",
"description": "An array of query parameters that may be used for the user's search string.",
"items": {
"type": "string"
}
},
"codeParamName": {
"type": "string",
"title": "Partner Code Parameter Name",
"description": "The name of the query parameter for the partner code."
},
"taggedCodes": {
"type": "array",
"title": "Partner Codes",
"description": "An array of partner codes to match against the parameters in the url. Matching these codes will report the SERP as tagged.",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-._]*$"
}
},
"expectedOrganicCodes": {
"type": "array",
"title": "Expected Organic Codes",
"description": "An array of partner codes to match against the parameters in the url. Matching these codes will report the SERP as organic:none which means the user has done a search through the search engine's website rather than through SAP.",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-._]*$"
}
},
"organicCodes": {
"type": "array",
"title": "Organic Codes",
"description": "An array of partner codes to match against the parameters in the url. Matching these codes will report the SERP as organic:<partner code>, which means the search was performed organically rather than through a SAP.",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-._]*$"
}
},
"followOnParamNames": {
"type": "array",
"title": "Follow-on Search Parameter Names",
"description": "An array of query parameter names that are used when a follow-on search occurs.",
"items": {
"type": "string",
"pattern": "^[a-z0-9-._]*$"
}
},
"followOnCookies": {
"type": "array",
"title": "Follow-on Cookies",
"description": "An array of cookie details that are used to identify follow-on searches.",
"items": {
"type": "object",
"properties": {
"extraCodeParamName": {
"type": "string",
"description": "The query parameter name in the URL that indicates this might be a follow-on search.",
"pattern": "^[a-z0-9-._]*$"
},
"extraCodePrefixes": {
"type": "array",
"description": "Possible values for the query parameter in the URL that indicates this might be a follow-on search.",
"items": {
"type": "string",
"pattern": "^[a-zA-Z0-9-._]*$"
}
},
"host": {
"type": "string",
"description": "The hostname on which the cookie is stored.",
"pattern": "^[a-z0-9-._]*$"
},
"name": {
"type": "string",
"description": "The name of the cookie to check.",
"pattern": "^[a-zA-Z0-9-._]*$"
},
"codeParamName": {
"type": "string",
"description": "The name of parameter within the cookie.",
"pattern": "^[a-zA-Z0-9-._]*$"
}
}
}
},
"extraAdServersRegexps": {
"type": "array",
"title": "Extra Ad Server Regular Expressions",
"description": "An array of regular expressions that match URLs of potential ad servers.",
"items": {
"type": "string"
}
},
"adServerAttributes": {
"type": "array",
"title": "Ad Server Attributes",
"description": "An array of strings that potentially match data-attribute keys of anchors.",
"items": {
"type": "string"
}
},
"components": {
"type": "array",
"title": "Components",
"description": "An array of components that could be on the SERP.",
"items": {
"required": ["type"],
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "The type of component the anchor or DOM element should belong to.",
"pattern": "^[a-z](?:_?[a-z])*$"
},
"included": {
"type": "object",
"description": "Conditions that should be fulfilled.",
"properties": {
"parent": {
"title": "Parent",
"description": "The DOM element that should only contain elements applicable to a single component type.",
"type": "object",
"properties": {
"selector": {
"description": "If topDown is true for this component, then this will be the value used in querySelectorAll(). Otherwise, it will be the value to in closest() from the context of an anchor.",
"type": "string"
},
"eventListeners": {
"$ref": "#/definitions/eventListeners"
},
"skipCount": {
"$ref": "#/definitions/skipCount"
}
},
"required": ["selector"]
},
"children": {
"type": "array",
"title": "Children",
"description": "Child DOM elements of the parent. Optional.",
"items": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "The selector to use querySelectorAll from the context of the parent."
},
"type": {
"type": "string",
"description": "The component type to use if this child is present.",
"pattern": "^[a-z](?:_?[a-z])*$"
},
"countChildren": {
"type": "boolean",
"description": "Whether we should count all instances of the child element instead of anchor links found inside of the parent. Defaults to false."
},
"eventListeners": {
"$ref": "#/definitions/eventListeners"
},
"skipCount": {
"$ref": "#/definitions/skipCount"
}
},
"required": ["selector"]
}
},
"related": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "The selector to use querySelectorAll from the context of the parent. Any elements specified will have their click events registered and categorized as expanded unless explicitly overwritten in SearchSERPTelemetryChild."
}
},
"required": ["selector"]
}
},
"required": ["parent"]
},
"excluded": {
"type": "object",
"description": "Conditions that should not be included.",
"properties": {
"parent": {
"type": "object",
"properties": {
"selector": {
"type": "string",
"description": "The root DOM element that shouldn't be a parent from the context of the anchor being inspected."
}
},
"required": ["selector"]
}
}
},
"default": {
"type": "boolean",
"description": "Whether this component should be the fallback option if a link was included in both ad-related regular expressions as well as regular expressions matching non-ad elements but couldn't be categorized. Defaults to false."
},
"topDown": {
"type": "boolean",
"description": "Whether the component should be found first by using document.querySelectorAll on the parent selector definition. Defaults to false."
},
"dependentRequired": {
"topDown": ["included"]
}
}
}
},
"ignoreLinkRegexps": {
"type": "array",
"title": "Ignore links matching regular expressions",
"description": "Regular expressions matching links that should be ignored by the network observer.",
"items": {
"type": "string",
"description": "The matching regular expression."
}
},
"nonAdsLinkQueryParamNames": {
"type": "array",
"title": "Non-ads link query param names",
"description": "Query param names present in non-ads link that recover the link that will be redirected to.",
"items": {
"type": "string",
"string": "The query param name to examine."
}
},
"nonAdsLinkRegexps": {
"type": "array",
"title": "Non-ads link matching regular expressions",
"description": "An array containing known patterns that match non-ad links from a search provider.",
"items": {
"type": "string",
"description": "The matching regular expression."
}
},
"shoppingTab": {
"type": "object",
"title": "Shopping Tab",
"properties": {
"selector": {
"type": "string",
"description": "The elements on the page to inspect for the shopping tab. Should be anchor elements."
},
"regexp": {
"type": "string",
"description": "The regular expression to match against a possible shopping tab. Must be provided if using this feature."
},
"inspectRegexpInSERP": {
"type": "boolean",
"description": "Whether the regexp should be used against hrefs the selector matches against."
}
},
"required": ["selector", "regexp"]
},
"domainExtraction": {
"type": "object",
"title": "Domain Extraction",
"description": "An array of methods for extracting domains from a SERP result.",
"properties": {
"ads": {
"type": "array",
"description": "An array of methods for extracting domains from ads.",
"items": {
"$ref": "#/definitions/extraction"
}
},
"nonAds": {
"type": "array",
"description": "An array of methods for extracting domains from non-ads.",
"items": {
"$ref": "#/definitions/extraction"
}
}
}
},
"isSPA": {
"type": "boolean",
"title": "Is Single Page App",
"description": "Whether the provider exhibits tendencies of a single page app, namely changes the entire contents of the page without having to reload."
},
"defaultPageQueryParam": {
"type": "object",
"title": "Default page query parameter",
"properties": {
"key": {
"type": "string",
"description": "The key corresponding to the query parameter that contains what type of search page is being shown."
},
"value": {
"type": "string",
"description": "The value corresponding to the query parameter that should be matched against."
}
},
"required": ["key", "value"]
}
},
"definitions": {
"eventListener": {
"title": "Event Listener",
"type": "object",
"description": "Event listeners attached to a component.",
"properties": {
"eventType": {
"title": "Event Type",
"description": "The type of event to listen for. Custom events, especially those with special logic like keydownEnter, can be used if the Desktop code has been updated.",
"type": "string",
"pattern": "^[a-z][A-Za-z]*$"
},
"target": {
"title": "Target",
"description": "The component type to report when the event is triggered. Uses the child component type (if exists), otherwise uses the parent component type.",
"type": "string",
"pattern": "^[a-z](?:_?[a-z])*$"
},
"action": {
"title": "Action",
"description": "The action to report when the event is triggered. If the event type is 'click', defaults to clicked. Otherwise, this should be provided.",
"type": "string",
"pattern": "^[a-z](?:_?[a-z])*$"
}
},
"required": ["eventType"]
},
"eventListeners": {
"title": "Event Listeners",
"description": "An array of Event Listeners to apply to elements.",
"type": "array",
"items": {
"$ref": "#/definitions/eventListener"
}
},
"extraction": {
"anyOf": [
{
"type": "object",
"properties": {
"selectors": {
"type": "string",
"description": "The query to inspect all elements on the SERP."
},
"method": {
"enum": ["dataAttribute"],
"description": "The extraction method used for the query."
},
"options": {
"type": "object",
"properties": {
"dataAttributeKey": {
"type": "string",
"description": "The data attribute key that will be looked up in order to retrieve its data attribute value."
}
},
"required": ["dataAttributeKey"]
}
},
"required": ["selectors", "method", "options"]
},
{
"type": "object",
"properties": {
"selectors": {
"type": "string",
"description": "The query to use to inspect all elements on the SERP."
},
"method": {
"enum": ["href"],
"description": "The extraction method to use for the query."
},
"options": {
"type": "object",
"properties": {
"queryParamKey": {
"type": "string",
"description": "The query parameter key to inspect in the href."
},
"queryParamValueIsHref": {
"type": "boolean",
"description": "Whether the query param value is expected to contain an href."
}
},
"required": ["queryParamKey"]
}
},
"required": ["selectors", "method"]
},
{
"type": "object",
"properties": {
"selectors": {
"type": "string",
"description": "The query to use to inspect all elements on the SERP."
},
"method": {
"enum": ["textContent"],
"description": "The extraction method to use for the query."
}
},
"required": ["selectors", "method"]
}
]
},
"skipCount": {
"title": "Skip Count",
"description": "Whether to skip reporting of the count of these elements to ad_impressions. Defaults to false.",
"type": "boolean"
}
}
}
|