@revclamp/google-ads-transparency-mcp 1.0.8 → 1.0.10
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/README.md +1 -0
- package/actor_config.json +1 -1
- package/index.mjs +2 -0
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/mcp_server.mjs +1 -1
- package/src/rpc_client.mjs +373 -11
package/README.md
CHANGED
|
@@ -122,6 +122,7 @@ npm test
|
|
|
122
122
|
| **[RevClamp Enterprise](https://revclamp.com/mcp)** | [`revclamp-mcp`](https://www.npmjs.com/package/revclamp-mcp) | Pre-deploy subscription revenue, webhook idempotency & compliance guard (`Stripe`, `Paddle`, `Lemon Squeezy`, `Shopify`) |
|
|
123
123
|
| **[RevClamp AdPulse](https://apify.com/revclamp/google-ads-transparency-mcp)** | [`@revclamp/google-ads-transparency-mcp`](https://www.npmjs.com/package/@revclamp/google-ads-transparency-mcp) | Verified Google Ads advertiser entity disambiguation & active/historical creative intelligence |
|
|
124
124
|
| **[RevClamp TalentPulse](https://apify.com/revclamp/unified-ats-jobs-mcp)** | [`@revclamp/unified-ats-jobs-mcp`](https://www.npmjs.com/package/@revclamp/unified-ats-jobs-mcp) | Unified 5-in-1 B2B ATS job postings, salary ranges & tech-stack hiring signals (`Greenhouse`, `Workday CXS`, `Ashby`, `Lever`, `SmartRecruiters`) |
|
|
125
|
+
| **[RevClamp ContactPulse](https://apify.com/revclamp/b2b-domain-contact-enricher-mcp)** | [`@revclamp/b2b-domain-contact-enricher-mcp`](https://www.npmjs.com/package/@revclamp/b2b-domain-contact-enricher-mcp) | B2B domain role-contact enrichment, RFC 9116 `security.txt` audit & DNS-over-HTTPS MX/SPF/DMARC deliverability posture |
|
|
125
126
|
|
|
126
127
|
## Terms of Use, Data Provenance & Independent Tool Disclaimer
|
|
127
128
|
|
package/actor_config.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
],
|
|
22
22
|
"manifest": {
|
|
23
23
|
"name": "google-ads-transparency-mcp",
|
|
24
|
-
"version": "1.0.
|
|
24
|
+
"version": "1.0.10",
|
|
25
25
|
"title": "RevClamp AdPulse - Google Ads Transparency Scraper & MCP",
|
|
26
26
|
"websiteUrl": "https://revclamp.com",
|
|
27
27
|
"description": "Find verified Google Ads advertiser entities and extract active or historical ad creatives (Text, Image, Video), preview links, and run dates without browser or proxy overhead. Independent intelligence tool by RevClamp; not affiliated with or endorsed by Google LLC."
|
package/index.mjs
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
COMPOSITE_CURSOR_PREFIX,
|
|
29
29
|
MAX_CURSOR_LENGTH,
|
|
30
30
|
MAX_QUERY_LENGTH,
|
|
31
|
+
KNOWN_ADVERTISER_DIRECTORY,
|
|
31
32
|
CORPORATE_LEGAL_SUFFIX_TOKENS,
|
|
32
33
|
collapseDottedAcronyms,
|
|
33
34
|
foldBrandText,
|
|
@@ -100,6 +101,7 @@ export {
|
|
|
100
101
|
COMPOSITE_CURSOR_PREFIX,
|
|
101
102
|
MAX_CURSOR_LENGTH,
|
|
102
103
|
MAX_QUERY_LENGTH,
|
|
104
|
+
KNOWN_ADVERTISER_DIRECTORY,
|
|
103
105
|
CORPORATE_LEGAL_SUFFIX_TOKENS,
|
|
104
106
|
collapseDottedAcronyms,
|
|
105
107
|
foldBrandText,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revclamp/google-ads-transparency-mcp",
|
|
3
3
|
"mcpName": "com.revclamp/google-ads-transparency-mcp",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.10",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "RevClamp AdPulse - Google Ads Transparency Scraper & MCP. Find verified advertiser entities and extract active or historical ad creatives (Text, Image, Video), preview links, and run dates with zero browser overhead. Independent tool by RevClamp; not affiliated with Google LLC.",
|
|
7
7
|
"homepage": "https://revclamp.com",
|
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "com.revclamp/google-ads-transparency-mcp",
|
|
4
4
|
"title": "RevClamp AdPulse - Google Ads Transparency Scraper & MCP",
|
|
5
5
|
"description": "Google Ads Transparency Center advertiser & creative intelligence MCP server by RevClamp.",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.10",
|
|
7
7
|
"websiteUrl": "https://revclamp.com",
|
|
8
8
|
"repository": {
|
|
9
9
|
"url": "https://github.com/lhphong09t2/revclamp-mcp",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"registryType": "npm",
|
|
28
28
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
29
29
|
"identifier": "@revclamp/google-ads-transparency-mcp",
|
|
30
|
-
"version": "1.0.
|
|
30
|
+
"version": "1.0.10",
|
|
31
31
|
"runtimeHint": "npx",
|
|
32
32
|
"transport": {
|
|
33
33
|
"type": "stdio"
|
package/src/mcp_server.mjs
CHANGED
|
@@ -43,7 +43,7 @@ export const ENCODED_BRAND_ICON_DATA_URI = `data:image/svg+xml;utf8,${encodeURIC
|
|
|
43
43
|
export const MCP_SERVER_INFO = Object.freeze({
|
|
44
44
|
name: 'google-ads-transparency-mcp',
|
|
45
45
|
title: 'RevClamp AdPulse - Google Ads Transparency Scraper & MCP',
|
|
46
|
-
version: '1.0.
|
|
46
|
+
version: '1.0.9',
|
|
47
47
|
description:
|
|
48
48
|
'Find verified Google Ads advertiser entities and extract active or historical ad creatives (Text, Image, Video), preview links, and run dates. Independent intelligence tool by RevClamp; not affiliated with or endorsed by Google LLC.',
|
|
49
49
|
// Forward-compatible MCP Registry & Glama metadata extensions (ignored by older stdio clients)
|
package/src/rpc_client.mjs
CHANGED
|
@@ -56,6 +56,261 @@ export const MAX_QUERY_LENGTH = 512;
|
|
|
56
56
|
const MIN_VALID_EPOCH_SEC = 946684800; // 2000-01-01T00:00:00Z
|
|
57
57
|
const MAX_VALID_EPOCH_SEC = 4102444800; // 2100-01-01T00:00:00Z
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Curated directory of verified Google Ads Transparency legal entities (`AR...`)
|
|
61
|
+
* for top global brands so common queries resolve in 0 SearchSuggestions RPC calls
|
|
62
|
+
* and degrade gracefully if upstream SearchSuggestions encounters rate-limiting.
|
|
63
|
+
*/
|
|
64
|
+
export const KNOWN_ADVERTISER_DIRECTORY = Object.freeze(
|
|
65
|
+
Object.assign(Object.create(null), {
|
|
66
|
+
nike: Object.freeze({
|
|
67
|
+
advertiserId: 'AR16735076323512287233',
|
|
68
|
+
advertiserName: 'Nike, Inc.',
|
|
69
|
+
regionCode: 'US',
|
|
70
|
+
minAds: 9000,
|
|
71
|
+
maxAds: 10000,
|
|
72
|
+
}),
|
|
73
|
+
stripe: Object.freeze({
|
|
74
|
+
advertiserId: 'AR16951989901585285121',
|
|
75
|
+
advertiserName: 'Stripe, Inc.',
|
|
76
|
+
regionCode: 'US',
|
|
77
|
+
minAds: 8000,
|
|
78
|
+
maxAds: 9000,
|
|
79
|
+
}),
|
|
80
|
+
shopify: Object.freeze({
|
|
81
|
+
advertiserId: 'AR01625195283841286145',
|
|
82
|
+
advertiserName: 'Shopify Inc.',
|
|
83
|
+
regionCode: 'CA',
|
|
84
|
+
minAds: 40000,
|
|
85
|
+
maxAds: 50000,
|
|
86
|
+
}),
|
|
87
|
+
apple: Object.freeze({
|
|
88
|
+
advertiserId: 'AR03186575737440174081',
|
|
89
|
+
advertiserName: 'Apple Inc.',
|
|
90
|
+
regionCode: 'US',
|
|
91
|
+
minAds: 1000,
|
|
92
|
+
maxAds: 2000,
|
|
93
|
+
}),
|
|
94
|
+
openai: Object.freeze({
|
|
95
|
+
advertiserId: 'AR02788840342533701633',
|
|
96
|
+
advertiserName: 'OpenAI OpCo, LLC',
|
|
97
|
+
regionCode: 'US',
|
|
98
|
+
minAds: 40000,
|
|
99
|
+
maxAds: 50000,
|
|
100
|
+
}),
|
|
101
|
+
hubspot: Object.freeze({
|
|
102
|
+
advertiserId: 'AR10072600183532683265',
|
|
103
|
+
advertiserName: 'Hubspot, Inc.',
|
|
104
|
+
regionCode: 'US',
|
|
105
|
+
minAds: 2000,
|
|
106
|
+
maxAds: 3000,
|
|
107
|
+
}),
|
|
108
|
+
google: Object.freeze({
|
|
109
|
+
advertiserId: 'AR00753945370957971457',
|
|
110
|
+
advertiserName: 'Google LLC',
|
|
111
|
+
regionCode: 'US',
|
|
112
|
+
minAds: 21,
|
|
113
|
+
maxAds: 21,
|
|
114
|
+
}),
|
|
115
|
+
microsoft: Object.freeze({
|
|
116
|
+
advertiserId: 'AR15495076796520464385',
|
|
117
|
+
advertiserName: 'Microsoft Corporation',
|
|
118
|
+
regionCode: 'US',
|
|
119
|
+
minAds: 60000,
|
|
120
|
+
maxAds: 70000,
|
|
121
|
+
}),
|
|
122
|
+
amazon: Object.freeze({
|
|
123
|
+
advertiserId: 'AR12815412684405080065',
|
|
124
|
+
advertiserName: 'Amazon',
|
|
125
|
+
regionCode: 'US',
|
|
126
|
+
minAds: 2000,
|
|
127
|
+
maxAds: 3000,
|
|
128
|
+
}),
|
|
129
|
+
meta: Object.freeze({
|
|
130
|
+
advertiserId: 'AR17753757646030110721',
|
|
131
|
+
advertiserName: 'Meta',
|
|
132
|
+
regionCode: 'US',
|
|
133
|
+
minAds: 500,
|
|
134
|
+
maxAds: 600,
|
|
135
|
+
}),
|
|
136
|
+
netflix: Object.freeze({
|
|
137
|
+
advertiserId: 'AR11279752625278418945',
|
|
138
|
+
advertiserName: 'Netflix, Inc.',
|
|
139
|
+
regionCode: 'US',
|
|
140
|
+
minAds: 9000,
|
|
141
|
+
maxAds: 10000,
|
|
142
|
+
}),
|
|
143
|
+
airbnb: Object.freeze({
|
|
144
|
+
advertiserId: 'AR15908226811872411649',
|
|
145
|
+
advertiserName: 'Airbnb, Inc.',
|
|
146
|
+
regionCode: 'US',
|
|
147
|
+
minAds: 1000000,
|
|
148
|
+
maxAds: 1100000,
|
|
149
|
+
}),
|
|
150
|
+
uber: Object.freeze({
|
|
151
|
+
advertiserId: 'AR10766558596670947329',
|
|
152
|
+
advertiserName: 'Uber B.V.',
|
|
153
|
+
regionCode: 'NL',
|
|
154
|
+
minAds: 20000,
|
|
155
|
+
maxAds: 30000,
|
|
156
|
+
}),
|
|
157
|
+
salesforce: Object.freeze({
|
|
158
|
+
advertiserId: 'AR14047752120044617729',
|
|
159
|
+
advertiserName: 'Salesforce, Inc.',
|
|
160
|
+
regionCode: 'US',
|
|
161
|
+
minAds: 20000,
|
|
162
|
+
maxAds: 30000,
|
|
163
|
+
}),
|
|
164
|
+
adobe: Object.freeze({
|
|
165
|
+
advertiserId: 'AR15000638237259595777',
|
|
166
|
+
advertiserName: 'Adobe, Inc',
|
|
167
|
+
regionCode: 'US',
|
|
168
|
+
minAds: 100000,
|
|
169
|
+
maxAds: 200000,
|
|
170
|
+
}),
|
|
171
|
+
cloudflare: Object.freeze({
|
|
172
|
+
advertiserId: 'AR10379917531786772481',
|
|
173
|
+
advertiserName: 'Cloudflare, Inc.',
|
|
174
|
+
regionCode: 'US',
|
|
175
|
+
minAds: 500,
|
|
176
|
+
maxAds: 600,
|
|
177
|
+
}),
|
|
178
|
+
datadog: Object.freeze({
|
|
179
|
+
advertiserId: 'AR02089091059349979137',
|
|
180
|
+
advertiserName: 'DATADOG, INC.',
|
|
181
|
+
regionCode: 'US',
|
|
182
|
+
minAds: 9000,
|
|
183
|
+
maxAds: 10000,
|
|
184
|
+
}),
|
|
185
|
+
datadoghq: Object.freeze({
|
|
186
|
+
advertiserId: 'AR02089091059349979137',
|
|
187
|
+
advertiserName: 'DATADOG, INC.',
|
|
188
|
+
regionCode: 'US',
|
|
189
|
+
minAds: 9000,
|
|
190
|
+
maxAds: 10000,
|
|
191
|
+
}),
|
|
192
|
+
vercel: Object.freeze({
|
|
193
|
+
advertiserId: 'AR03920035274037395457',
|
|
194
|
+
advertiserName: 'Vercel Inc.',
|
|
195
|
+
regionCode: 'US',
|
|
196
|
+
minAds: 200,
|
|
197
|
+
maxAds: 300,
|
|
198
|
+
}),
|
|
199
|
+
figma: Object.freeze({
|
|
200
|
+
advertiserId: 'AR15466204033491927041',
|
|
201
|
+
advertiserName: 'Figma INC',
|
|
202
|
+
regionCode: 'US',
|
|
203
|
+
minAds: 1000,
|
|
204
|
+
maxAds: 2000,
|
|
205
|
+
}),
|
|
206
|
+
atlassian: Object.freeze({
|
|
207
|
+
advertiserId: 'AR16220030717323640833',
|
|
208
|
+
advertiserName: 'Atlassian US, Inc.',
|
|
209
|
+
regionCode: 'US',
|
|
210
|
+
minAds: 20000,
|
|
211
|
+
maxAds: 30000,
|
|
212
|
+
}),
|
|
213
|
+
snowflake: Object.freeze({
|
|
214
|
+
advertiserId: 'AR00247099845179867137',
|
|
215
|
+
advertiserName: 'Snowflake Inc.',
|
|
216
|
+
regionCode: 'US',
|
|
217
|
+
minAds: 4000,
|
|
218
|
+
maxAds: 5000,
|
|
219
|
+
}),
|
|
220
|
+
twilio: Object.freeze({
|
|
221
|
+
advertiserId: 'AR18227580619968217089',
|
|
222
|
+
advertiserName: 'Twilio Inc.',
|
|
223
|
+
regionCode: 'US',
|
|
224
|
+
minAds: 1000,
|
|
225
|
+
maxAds: 2000,
|
|
226
|
+
}),
|
|
227
|
+
booking: Object.freeze({
|
|
228
|
+
advertiserId: 'AR02934798844673654785',
|
|
229
|
+
advertiserName: 'Booking.com',
|
|
230
|
+
regionCode: 'NL',
|
|
231
|
+
minAds: 16500000,
|
|
232
|
+
maxAds: 16600000,
|
|
233
|
+
}),
|
|
234
|
+
oracle: Object.freeze({
|
|
235
|
+
advertiserId: 'AR08687048956523315201',
|
|
236
|
+
advertiserName: 'Oracle America, Inc.',
|
|
237
|
+
regionCode: 'US',
|
|
238
|
+
minAds: 3000,
|
|
239
|
+
maxAds: 4000,
|
|
240
|
+
}),
|
|
241
|
+
sap: Object.freeze({
|
|
242
|
+
advertiserId: 'AR14859734842907557889',
|
|
243
|
+
advertiserName: 'SAP SE',
|
|
244
|
+
regionCode: 'DE',
|
|
245
|
+
minAds: 2000,
|
|
246
|
+
maxAds: 3000,
|
|
247
|
+
}),
|
|
248
|
+
cisco: Object.freeze({
|
|
249
|
+
advertiserId: 'AR13942224429984514049',
|
|
250
|
+
advertiserName: 'Cisco Systems, Inc.',
|
|
251
|
+
regionCode: 'US',
|
|
252
|
+
minAds: 7000,
|
|
253
|
+
maxAds: 8000,
|
|
254
|
+
}),
|
|
255
|
+
nvidia: Object.freeze({
|
|
256
|
+
advertiserId: 'AR01839840586606051329',
|
|
257
|
+
advertiserName: 'NVIDIA Corporation',
|
|
258
|
+
regionCode: 'US',
|
|
259
|
+
minAds: 600,
|
|
260
|
+
maxAds: 700,
|
|
261
|
+
}),
|
|
262
|
+
canva: Object.freeze({
|
|
263
|
+
advertiserId: 'AR06374349942554624001',
|
|
264
|
+
advertiserName: 'Canva, Pty Ltd',
|
|
265
|
+
regionCode: 'AU',
|
|
266
|
+
minAds: 30000,
|
|
267
|
+
maxAds: 40000,
|
|
268
|
+
}),
|
|
269
|
+
asana: Object.freeze({
|
|
270
|
+
advertiserId: 'AR06554691289986629633',
|
|
271
|
+
advertiserName: 'Asana, Inc.',
|
|
272
|
+
regionCode: 'US',
|
|
273
|
+
minAds: 6000,
|
|
274
|
+
maxAds: 7000,
|
|
275
|
+
}),
|
|
276
|
+
zendesk: Object.freeze({
|
|
277
|
+
advertiserId: 'AR13756467712907804673',
|
|
278
|
+
advertiserName: 'Zendesk, Inc.',
|
|
279
|
+
regionCode: 'US',
|
|
280
|
+
minAds: 3000,
|
|
281
|
+
maxAds: 4000,
|
|
282
|
+
}),
|
|
283
|
+
okta: Object.freeze({
|
|
284
|
+
advertiserId: 'AR10734849505959608321',
|
|
285
|
+
advertiserName: 'Okta, Inc',
|
|
286
|
+
regionCode: 'US',
|
|
287
|
+
minAds: 1000,
|
|
288
|
+
maxAds: 2000,
|
|
289
|
+
}),
|
|
290
|
+
crowdstrike: Object.freeze({
|
|
291
|
+
advertiserId: 'AR13642683652595777537',
|
|
292
|
+
advertiserName: 'CROWDSTRIKE, INC.',
|
|
293
|
+
regionCode: 'US',
|
|
294
|
+
minAds: 8000,
|
|
295
|
+
maxAds: 9000,
|
|
296
|
+
}),
|
|
297
|
+
servicenow: Object.freeze({
|
|
298
|
+
advertiserId: 'AR04119835984416210945',
|
|
299
|
+
advertiserName: 'ServiceNow, Inc',
|
|
300
|
+
regionCode: 'US',
|
|
301
|
+
minAds: 10000,
|
|
302
|
+
maxAds: 20000,
|
|
303
|
+
}),
|
|
304
|
+
workday: Object.freeze({
|
|
305
|
+
advertiserId: 'AR09563861960156512257',
|
|
306
|
+
advertiserName: 'Workday, Inc.',
|
|
307
|
+
regionCode: 'US',
|
|
308
|
+
minAds: 5000,
|
|
309
|
+
maxAds: 6000,
|
|
310
|
+
}),
|
|
311
|
+
})
|
|
312
|
+
);
|
|
313
|
+
|
|
59
314
|
/**
|
|
60
315
|
* Canonical Google Ads Geo Target Criterion IDs mapped by ISO 3166-1 alpha-2 country code.
|
|
61
316
|
* Verified against live `LookupService/GetCreativeById` field `17` (`{ "1": 2840, "5": 20261104 }`)
|
|
@@ -429,6 +684,13 @@ export const CORPORATE_LEGAL_SUFFIX_TOKENS = new Set([
|
|
|
429
684
|
'lp',
|
|
430
685
|
'holdings',
|
|
431
686
|
'holding',
|
|
687
|
+
'opco',
|
|
688
|
+
'holdco',
|
|
689
|
+
'topco',
|
|
690
|
+
'bidco',
|
|
691
|
+
'midco',
|
|
692
|
+
'newco',
|
|
693
|
+
'finco',
|
|
432
694
|
'group',
|
|
433
695
|
'international',
|
|
434
696
|
'global',
|
|
@@ -651,10 +913,18 @@ export function parseBrandQueryTokens(rawQuery) {
|
|
|
651
913
|
: rawBrandTokens;
|
|
652
914
|
|
|
653
915
|
const brandStem = brandTokens[0] || foldedStemSource.replace(/[^\p{L}\p{N}]/gu, '');
|
|
654
|
-
const
|
|
655
|
-
|
|
916
|
+
const candidateStemWithoutHq =
|
|
917
|
+
brandStem.length >= 6 && brandStem.endsWith('hq')
|
|
656
918
|
? brandStem.slice(0, -2)
|
|
657
919
|
: brandStem;
|
|
920
|
+
const brandStemWithoutHq =
|
|
921
|
+
candidateStemWithoutHq !== brandStem &&
|
|
922
|
+
brandTokens.length === 1 &&
|
|
923
|
+
(isDomainQuery ||
|
|
924
|
+
Object.hasOwn(KNOWN_ADVERTISER_DIRECTORY, brandStem) ||
|
|
925
|
+
Object.hasOwn(KNOWN_ADVERTISER_DIRECTORY, candidateStemWithoutHq))
|
|
926
|
+
? candidateStemWithoutHq
|
|
927
|
+
: brandStem;
|
|
658
928
|
|
|
659
929
|
return {
|
|
660
930
|
rawQuery: trimmed,
|
|
@@ -1273,8 +1543,18 @@ export function scoreAdvertiserCandidate(candidate, queryMeta, preferredCountry
|
|
|
1273
1543
|
? Boolean(leadingEntityWords[0] === brandTokens[0] && allBrandTokensPresentAsWords)
|
|
1274
1544
|
: firstWordMatchesStem;
|
|
1275
1545
|
|
|
1546
|
+
const hasHqStemReduction = Boolean(
|
|
1547
|
+
brandTokens.length === 1 &&
|
|
1548
|
+
brandStemWithoutHq &&
|
|
1549
|
+
brandStemWithoutHq !== brandStem &&
|
|
1550
|
+
brandStemWithoutHq.length >= 2
|
|
1551
|
+
);
|
|
1276
1552
|
let domainConcatPrefixWords = [];
|
|
1277
|
-
if (
|
|
1553
|
+
if (
|
|
1554
|
+
(queryMeta?.isDomainQuery || hasHqStemReduction) &&
|
|
1555
|
+
brandStemWithoutHq &&
|
|
1556
|
+
brandStemWithoutHq.length >= 2
|
|
1557
|
+
) {
|
|
1278
1558
|
for (const wordList of [leadingEntityWords, nameWords]) {
|
|
1279
1559
|
let acc = '';
|
|
1280
1560
|
for (let k = 0; k < Math.min(5, wordList.length); k += 1) {
|
|
@@ -1294,12 +1574,11 @@ export function scoreAdvertiserCandidate(candidate, queryMeta, preferredCountry
|
|
|
1294
1574
|
}
|
|
1295
1575
|
|
|
1296
1576
|
const domainStemPrefixMatch = Boolean(
|
|
1297
|
-
queryMeta?.isDomainQuery &&
|
|
1577
|
+
(queryMeta?.isDomainQuery || hasHqStemReduction) &&
|
|
1298
1578
|
brandStemWithoutHq &&
|
|
1299
1579
|
brandStemWithoutHq.length >= 2 &&
|
|
1300
|
-
(
|
|
1301
|
-
|
|
1302
|
-
domainConcatPrefixWords.length > 0)
|
|
1580
|
+
(brandTokens.length <= 1 || allBrandTokensPresentAsWords) &&
|
|
1581
|
+
(leadingEntityWords[0] === brandStemWithoutHq || domainConcatPrefixWords.length > 0)
|
|
1303
1582
|
);
|
|
1304
1583
|
|
|
1305
1584
|
const matchedCoreTokens = exactBrandWordMatch
|
|
@@ -1529,10 +1808,15 @@ export async function executeGoogleAdsRpcPost(endpointUrl, fReqPayload, options
|
|
|
1529
1808
|
headers: {
|
|
1530
1809
|
'content-type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
|
1531
1810
|
accept: 'application/json, text/plain, */*',
|
|
1811
|
+
'accept-language': 'en-US,en;q=0.9',
|
|
1532
1812
|
origin: 'https://adstransparency.google.com',
|
|
1533
1813
|
referer: 'https://adstransparency.google.com/',
|
|
1814
|
+
'sec-fetch-dest': 'empty',
|
|
1815
|
+
'sec-fetch-mode': 'cors',
|
|
1816
|
+
'sec-fetch-site': 'same-origin',
|
|
1817
|
+
'x-same-domain': '1',
|
|
1534
1818
|
'user-agent':
|
|
1535
|
-
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
1819
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36',
|
|
1536
1820
|
},
|
|
1537
1821
|
body: encodedBody,
|
|
1538
1822
|
redirect: 'manual',
|
|
@@ -1942,12 +2226,66 @@ export async function resolveAdvertiserEntities(options = {}) {
|
|
|
1942
2226
|
};
|
|
1943
2227
|
}
|
|
1944
2228
|
|
|
1945
|
-
//
|
|
2229
|
+
// Match single-brand or domain stem against KNOWN_ADVERTISER_DIRECTORY when !includeSubsidiaries
|
|
2230
|
+
const directoryKey =
|
|
2231
|
+
queryMeta.brandTokens.length === 1 ? String(queryMeta.brandStem || '').toLowerCase() : '';
|
|
2232
|
+
const fallbackDirectoryKey =
|
|
2233
|
+
queryMeta.brandTokens.length === 1
|
|
2234
|
+
? String(queryMeta.brandStemWithoutHq || '').toLowerCase()
|
|
2235
|
+
: '';
|
|
2236
|
+
const rawKnownEntry = directoryKey
|
|
2237
|
+
? (Object.hasOwn(KNOWN_ADVERTISER_DIRECTORY, directoryKey)
|
|
2238
|
+
? KNOWN_ADVERTISER_DIRECTORY[directoryKey]
|
|
2239
|
+
: null) ||
|
|
2240
|
+
(fallbackDirectoryKey && Object.hasOwn(KNOWN_ADVERTISER_DIRECTORY, fallbackDirectoryKey)
|
|
2241
|
+
? KNOWN_ADVERTISER_DIRECTORY[fallbackDirectoryKey]
|
|
2242
|
+
: null) ||
|
|
2243
|
+
null
|
|
2244
|
+
: null;
|
|
2245
|
+
const normalizedFilterCountry = rawCountry === 'UK' ? 'GB' : rawCountry;
|
|
2246
|
+
const knownDirectoryEntity =
|
|
2247
|
+
rawKnownEntry &&
|
|
2248
|
+
(!normalizedFilterCountry ||
|
|
2249
|
+
normalizedFilterCountry === 'ALL' ||
|
|
2250
|
+
normalizedFilterCountry === rawKnownEntry.regionCode)
|
|
2251
|
+
? scoreAdvertiserCandidate(rawKnownEntry, queryMeta, normalizedFilterCountry)
|
|
2252
|
+
: null;
|
|
2253
|
+
|
|
2254
|
+
const singleEntityDirectoryEligible = maxEntities === 1;
|
|
2255
|
+
const shouldUseDirectoryBeforeRpc =
|
|
2256
|
+
Boolean(knownDirectoryEntity) &&
|
|
2257
|
+
singleEntityDirectoryEligible &&
|
|
2258
|
+
options.preferDirectory === true;
|
|
2259
|
+
|
|
2260
|
+
if (shouldUseDirectoryBeforeRpc) {
|
|
2261
|
+
return {
|
|
2262
|
+
ok: true,
|
|
2263
|
+
status: 'OK',
|
|
2264
|
+
resolutionSource: 'KNOWN_ADVERTISER_DIRECTORY',
|
|
2265
|
+
queryMeta,
|
|
2266
|
+
primaryEntity: knownDirectoryEntity,
|
|
2267
|
+
selectedEntities: [knownDirectoryEntity],
|
|
2268
|
+
allCandidates: [knownDirectoryEntity],
|
|
2269
|
+
rpcAttempts: 0,
|
|
2270
|
+
billableCount: 0,
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
// Multi-token domains (e.g. on-running.com) join all tokens ("on running") rather than truncating to first token;
|
|
2275
|
+
// single-token -hq domains/queries (e.g. datadoghq.com, datadoghq) search by brandStemWithoutHq ("datadog").
|
|
2276
|
+
const effectiveSingleTokenStem =
|
|
2277
|
+
queryMeta.brandStemWithoutHq && queryMeta.brandStemWithoutHq !== queryMeta.brandStem
|
|
2278
|
+
? queryMeta.brandStemWithoutHq
|
|
2279
|
+
: queryMeta.brandStem;
|
|
1946
2280
|
const searchQueryStr = queryMeta.isDomainQuery
|
|
1947
2281
|
? queryMeta.brandTokens.length > 1
|
|
1948
2282
|
? queryMeta.brandTokens.join(' ')
|
|
1949
|
-
:
|
|
1950
|
-
: queryMeta.
|
|
2283
|
+
: effectiveSingleTokenStem
|
|
2284
|
+
: queryMeta.brandTokens.length === 1 &&
|
|
2285
|
+
queryMeta.brandStemWithoutHq &&
|
|
2286
|
+
queryMeta.brandStemWithoutHq !== queryMeta.brandStem
|
|
2287
|
+
? queryMeta.brandStemWithoutHq
|
|
2288
|
+
: queryMeta.rawQuery;
|
|
1951
2289
|
|
|
1952
2290
|
const endpointUrl = options.endpointUrl || GOOGLE_ADS_RPC_ENDPOINTS.SearchSuggestions;
|
|
1953
2291
|
const rpcRes = await executeGoogleAdsRpcPost(
|
|
@@ -1957,6 +2295,24 @@ export async function resolveAdvertiserEntities(options = {}) {
|
|
|
1957
2295
|
);
|
|
1958
2296
|
|
|
1959
2297
|
if (!rpcRes.ok) {
|
|
2298
|
+
if (
|
|
2299
|
+
rpcRes.status === 'UPSTREAM_RATE_LIMITED' &&
|
|
2300
|
+
knownDirectoryEntity &&
|
|
2301
|
+
singleEntityDirectoryEligible &&
|
|
2302
|
+
options.fallbackToDirectoryOnRateLimit !== false
|
|
2303
|
+
) {
|
|
2304
|
+
return {
|
|
2305
|
+
ok: true,
|
|
2306
|
+
status: 'OK',
|
|
2307
|
+
resolutionSource: 'KNOWN_ADVERTISER_DIRECTORY_FALLBACK',
|
|
2308
|
+
queryMeta,
|
|
2309
|
+
primaryEntity: knownDirectoryEntity,
|
|
2310
|
+
selectedEntities: [knownDirectoryEntity],
|
|
2311
|
+
allCandidates: [knownDirectoryEntity],
|
|
2312
|
+
rpcAttempts: rpcRes.attempts,
|
|
2313
|
+
billableCount: 0,
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
1960
2316
|
return {
|
|
1961
2317
|
ok: false,
|
|
1962
2318
|
status: rpcRes.status,
|
|
@@ -2760,7 +3116,13 @@ export async function fetchAndExtractStaticAdCopy(previewUrl, options = {}) {
|
|
|
2760
3116
|
method: 'GET',
|
|
2761
3117
|
headers: {
|
|
2762
3118
|
accept: 'application/javascript, text/javascript, text/plain, */*',
|
|
3119
|
+
'accept-language': 'en-US,en;q=0.9',
|
|
2763
3120
|
referer: 'https://adstransparency.google.com/',
|
|
3121
|
+
'sec-fetch-dest': 'script',
|
|
3122
|
+
'sec-fetch-mode': 'no-cors',
|
|
3123
|
+
'sec-fetch-site': 'cross-site',
|
|
3124
|
+
'user-agent':
|
|
3125
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36',
|
|
2764
3126
|
},
|
|
2765
3127
|
redirect: 'manual',
|
|
2766
3128
|
signal: controller.signal,
|