@revclamp/google-ads-transparency-mcp 1.0.9 → 1.0.11
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/actor_config.json +1 -1
- package/package.json +3 -3
- package/server.json +2 -2
- package/src/rpc_client.mjs +143 -15
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.11",
|
|
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/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
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.11",
|
|
5
5
|
"type": "module",
|
|
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
|
|
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. Independent B2B tool by RevClamp.",
|
|
7
7
|
"homepage": "https://revclamp.com",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"keywords": [
|
|
31
31
|
"mcp",
|
|
32
|
+
"mcp-server",
|
|
32
33
|
"model-context-protocol",
|
|
33
34
|
"google-ads",
|
|
34
35
|
"ads-transparency",
|
|
@@ -38,7 +39,6 @@
|
|
|
38
39
|
"brand-safety",
|
|
39
40
|
"ppc",
|
|
40
41
|
"b2b-marketing",
|
|
41
|
-
"apify",
|
|
42
42
|
"revclamp"
|
|
43
43
|
],
|
|
44
44
|
"scripts": {
|
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.11",
|
|
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.11",
|
|
31
31
|
"runtimeHint": "npx",
|
|
32
32
|
"transport": {
|
|
33
33
|
"type": "stdio"
|
package/src/rpc_client.mjs
CHANGED
|
@@ -61,7 +61,8 @@ const MAX_VALID_EPOCH_SEC = 4102444800; // 2100-01-01T00:00:00Z
|
|
|
61
61
|
* for top global brands so common queries resolve in 0 SearchSuggestions RPC calls
|
|
62
62
|
* and degrade gracefully if upstream SearchSuggestions encounters rate-limiting.
|
|
63
63
|
*/
|
|
64
|
-
export const KNOWN_ADVERTISER_DIRECTORY = Object.freeze(
|
|
64
|
+
export const KNOWN_ADVERTISER_DIRECTORY = Object.freeze(
|
|
65
|
+
Object.assign(Object.create(null), {
|
|
65
66
|
nike: Object.freeze({
|
|
66
67
|
advertiserId: 'AR16735076323512287233',
|
|
67
68
|
advertiserName: 'Nike, Inc.',
|
|
@@ -230,7 +231,85 @@ export const KNOWN_ADVERTISER_DIRECTORY = Object.freeze({
|
|
|
230
231
|
minAds: 16500000,
|
|
231
232
|
maxAds: 16600000,
|
|
232
233
|
}),
|
|
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
|
+
);
|
|
234
313
|
|
|
235
314
|
/**
|
|
236
315
|
* Canonical Google Ads Geo Target Criterion IDs mapped by ISO 3166-1 alpha-2 country code.
|
|
@@ -605,6 +684,13 @@ export const CORPORATE_LEGAL_SUFFIX_TOKENS = new Set([
|
|
|
605
684
|
'lp',
|
|
606
685
|
'holdings',
|
|
607
686
|
'holding',
|
|
687
|
+
'opco',
|
|
688
|
+
'holdco',
|
|
689
|
+
'topco',
|
|
690
|
+
'bidco',
|
|
691
|
+
'midco',
|
|
692
|
+
'newco',
|
|
693
|
+
'finco',
|
|
608
694
|
'group',
|
|
609
695
|
'international',
|
|
610
696
|
'global',
|
|
@@ -827,10 +913,18 @@ export function parseBrandQueryTokens(rawQuery) {
|
|
|
827
913
|
: rawBrandTokens;
|
|
828
914
|
|
|
829
915
|
const brandStem = brandTokens[0] || foldedStemSource.replace(/[^\p{L}\p{N}]/gu, '');
|
|
830
|
-
const
|
|
831
|
-
|
|
916
|
+
const candidateStemWithoutHq =
|
|
917
|
+
brandStem.length >= 6 && brandStem.endsWith('hq')
|
|
832
918
|
? brandStem.slice(0, -2)
|
|
833
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;
|
|
834
928
|
|
|
835
929
|
return {
|
|
836
930
|
rawQuery: trimmed,
|
|
@@ -1449,8 +1543,18 @@ export function scoreAdvertiserCandidate(candidate, queryMeta, preferredCountry
|
|
|
1449
1543
|
? Boolean(leadingEntityWords[0] === brandTokens[0] && allBrandTokensPresentAsWords)
|
|
1450
1544
|
: firstWordMatchesStem;
|
|
1451
1545
|
|
|
1546
|
+
const hasHqStemReduction = Boolean(
|
|
1547
|
+
brandTokens.length === 1 &&
|
|
1548
|
+
brandStemWithoutHq &&
|
|
1549
|
+
brandStemWithoutHq !== brandStem &&
|
|
1550
|
+
brandStemWithoutHq.length >= 2
|
|
1551
|
+
);
|
|
1452
1552
|
let domainConcatPrefixWords = [];
|
|
1453
|
-
if (
|
|
1553
|
+
if (
|
|
1554
|
+
(queryMeta?.isDomainQuery || hasHqStemReduction) &&
|
|
1555
|
+
brandStemWithoutHq &&
|
|
1556
|
+
brandStemWithoutHq.length >= 2
|
|
1557
|
+
) {
|
|
1454
1558
|
for (const wordList of [leadingEntityWords, nameWords]) {
|
|
1455
1559
|
let acc = '';
|
|
1456
1560
|
for (let k = 0; k < Math.min(5, wordList.length); k += 1) {
|
|
@@ -1470,12 +1574,11 @@ export function scoreAdvertiserCandidate(candidate, queryMeta, preferredCountry
|
|
|
1470
1574
|
}
|
|
1471
1575
|
|
|
1472
1576
|
const domainStemPrefixMatch = Boolean(
|
|
1473
|
-
queryMeta?.isDomainQuery &&
|
|
1577
|
+
(queryMeta?.isDomainQuery || hasHqStemReduction) &&
|
|
1474
1578
|
brandStemWithoutHq &&
|
|
1475
1579
|
brandStemWithoutHq.length >= 2 &&
|
|
1476
|
-
(
|
|
1477
|
-
|
|
1478
|
-
domainConcatPrefixWords.length > 0)
|
|
1580
|
+
(brandTokens.length <= 1 || allBrandTokensPresentAsWords) &&
|
|
1581
|
+
(leadingEntityWords[0] === brandStemWithoutHq || domainConcatPrefixWords.length > 0)
|
|
1479
1582
|
);
|
|
1480
1583
|
|
|
1481
1584
|
const matchedCoreTokens = exactBrandWordMatch
|
|
@@ -2126,10 +2229,26 @@ export async function resolveAdvertiserEntities(options = {}) {
|
|
|
2126
2229
|
// Match single-brand or domain stem against KNOWN_ADVERTISER_DIRECTORY when !includeSubsidiaries
|
|
2127
2230
|
const directoryKey =
|
|
2128
2231
|
queryMeta.brandTokens.length === 1 ? String(queryMeta.brandStem || '').toLowerCase() : '';
|
|
2129
|
-
const
|
|
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;
|
|
2130
2246
|
const knownDirectoryEntity =
|
|
2131
|
-
rawKnownEntry &&
|
|
2132
|
-
|
|
2247
|
+
rawKnownEntry &&
|
|
2248
|
+
(!normalizedFilterCountry ||
|
|
2249
|
+
normalizedFilterCountry === 'ALL' ||
|
|
2250
|
+
normalizedFilterCountry === rawKnownEntry.regionCode)
|
|
2251
|
+
? scoreAdvertiserCandidate(rawKnownEntry, queryMeta, normalizedFilterCountry)
|
|
2133
2252
|
: null;
|
|
2134
2253
|
|
|
2135
2254
|
const singleEntityDirectoryEligible = maxEntities === 1;
|
|
@@ -2152,12 +2271,21 @@ export async function resolveAdvertiserEntities(options = {}) {
|
|
|
2152
2271
|
};
|
|
2153
2272
|
}
|
|
2154
2273
|
|
|
2155
|
-
// Multi-token domains (e.g. on-running.com) join all tokens ("on running") rather than truncating to first token
|
|
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;
|
|
2156
2280
|
const searchQueryStr = queryMeta.isDomainQuery
|
|
2157
2281
|
? queryMeta.brandTokens.length > 1
|
|
2158
2282
|
? queryMeta.brandTokens.join(' ')
|
|
2159
|
-
:
|
|
2160
|
-
: queryMeta.
|
|
2283
|
+
: effectiveSingleTokenStem
|
|
2284
|
+
: queryMeta.brandTokens.length === 1 &&
|
|
2285
|
+
queryMeta.brandStemWithoutHq &&
|
|
2286
|
+
queryMeta.brandStemWithoutHq !== queryMeta.brandStem
|
|
2287
|
+
? queryMeta.brandStemWithoutHq
|
|
2288
|
+
: queryMeta.rawQuery;
|
|
2161
2289
|
|
|
2162
2290
|
const endpointUrl = options.endpointUrl || GOOGLE_ADS_RPC_ENDPOINTS.SearchSuggestions;
|
|
2163
2291
|
const rpcRes = await executeGoogleAdsRpcPost(
|