Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungMCP Tool Poisoning: A Name Allowlist Is Not Enough(22.09.2026 um 18:56 Uhr)
Sichere ProgrammierungGiggleGigs: A Job Board That Actually Uses AI Where It Helps(22.09.2026 um 18:57 Uhr)
Sichere ProgrammierungThe Bootstrapped SaaS Flywheel: How to Hit $10k MRR Without VC Capital(22.09.2026 um 19:05 Uhr)
Sichere ProgrammierungThe container was running software nobody built(22.09.2026 um 19:08 Uhr)
Sichere ProgrammierungYour Terminal Tasks, Everywhere: Introducing Tasku Cloud(22.09.2026 um 19:08 Uhr)
Sichere ProgrammierungMCP Tool Poisoning: A Name Allowlist Is Not Enough(22.09.2026 um 18:56 Uhr)
Sichere ProgrammierungGiggleGigs: A Job Board That Actually Uses AI Where It Helps(22.09.2026 um 18:57 Uhr)
Sichere ProgrammierungThe Bootstrapped SaaS Flywheel: How to Hit $10k MRR Without VC Capital(22.09.2026 um 19:05 Uhr)
Sichere ProgrammierungThe container was running software nobody built(22.09.2026 um 19:08 Uhr)
Sichere ProgrammierungYour Terminal Tasks, Everywhere: Introducing Tasku Cloud(22.09.2026 um 19:08 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Build a Google Ads Competitor Intelligence Tool with Node.js

You've seen your competitor everywhere. Google Search. YouTube pre-rolls. Display ads on every site you visit. They're spending a fortune — and you want to know what's working. Good news: Google's Ad Transparency Center makes every ad p…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

You've seen your competitor everywhere. Google Search. YouTube pre-rolls. Display ads on every site you visit. They're spending a fortune — and you want to know what's working.



Good news: Google's Ad Transparency Center makes every ad public. Bad news: manually searching through it is like drinking from a firehose.



Let's build a Google Ads Competitor Intelligence Tool that:




  1. Pulls every ad a competitor is running on Google

  2. Tracks how long they've been running each creative

  3. Analyzes their messaging strategy

  4. Monitors for new campaign launches



If they found a winning ad formula, we want to know about it.






Why Google Ads Transparency Is a Goldmine



Since 2023, Google requires all advertisers to verify their identity and makes their ads publicly searchable. This means:




  • You can see every single ad any company runs

  • You can filter by region, format, and date range

  • You can track which ads they keep running (survival = profitable)



Most people don't know this exists. The few who do check it manually once a quarter. We're going to automate it.






The Stack





  • Node.js: Runtime


  • SociaVault API: Google Ad Library endpoints


  • better-sqlite3: Local tracking database


  • OpenAI: Ad copy analysis






Step 1: Setup






mkdir google-ad-spy
cd google-ad-spy
npm init -y
npm install axios better-sqlite3 openai dotenv






Create .env:




SOCIAVAULT_API_KEY=your_key_here
OPENAI_API_KEY=your_openai_key









Step 2: Set Up Tracking Database



Create db.js:




const Database = require('better-sqlite3');

const db = new Database('google-ads.db');

db.exec(`
CREATE TABLE IF NOT EXISTS advertisers (
id TEXT PRIMARY KEY,
name TEXT,
domain TEXT,
added_at TEXT DEFAULT (datetime('now'))
);

CREATE TABLE IF NOT EXISTS ads (
id TEXT PRIMARY KEY,
advertiser_id TEXT,
format TEXT,
content TEXT,
first_seen TEXT DEFAULT (datetime('now')),
last_seen TEXT DEFAULT (datetime('now')),
is_active BOOLEAN DEFAULT 1,
days_running INTEGER DEFAULT 0,
FOREIGN KEY (advertiser_id) REFERENCES advertisers(id)
);
`
);

module.exports = db;









Step 3: Find Advertisers



First, search for a company to get their advertiser ID:



Create spy.js:




require('dotenv').config();
const axios = require('axios');
const db = require('./db');
const OpenAI = require('openai');

const API_BASE = 'https://api.sociavault.com';
const headers = { 'Authorization': `Bearer ${process.env.SOCIAVAULT_API_KEY}` };
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function searchAdvertisers(query) {
console.log(`🔍 Searching Google Ad Library for "${query}"...\n`);

const { data } = await axios.get(
`${API_BASE}/v1/scrape/google-ad-library/search-advertisers`,
{ params: { query }, headers }
);

const advertisers = data.data || [];

if (advertisers.length === 0) {
console.log('No advertisers found.');
return [];
}

advertisers.forEach((adv, i) => {
console.log(` ${i + 1}. ${adv.name || adv.advertiserName}`);
console.log(` ID: ${adv.id || adv.advertiserId}`);
if (adv.domain) console.log(` Domain: ${adv.domain}`);
if (adv.verifiedStatus) console.log(` Verified: ${adv.verifiedStatus}`);
console.log();
});

return advertisers;
}









Step 4: Pull All Ads from a Competitor



Fetch every ad they're running with pagination:




async function getCompanyAds(identifier, options = {}) {
const isDomain = identifier.includes('.');

console.log(`📥 Fetching ads for ${identifier}...`);

let allAds = [];
let cursor = null;
let page = 0;

while (page < (options.maxPages || 10)) {
page++;

const params = {
...(isDomain ? { domain: identifier } : { advertiser_id: identifier }),
region: options.region || 'US',
topic: options.topic || 'all',
...(cursor && { cursor })
};

const { data } = await axios.get(
`${API_BASE}/v1/scrape/google-ad-library/company-ads`,
{ params, headers }
);

const ads = data.data?.ads || data.data || [];
allAds = allAds.concat(ads);

console.log(` Page ${page}: ${ads.length} ads`);

cursor = data.data?.cursor || data.data?.nextPageToken;
if (!cursor || ads.length === 0) break;

await new Promise(r => setTimeout(r, 1000));
}

console.log(` Total: ${allAds.length} ads\n`);

// Store in database
const advertiserId = isDomain ? identifier : identifier;

db.prepare('INSERT OR IGNORE INTO advertisers (id, name, domain) VALUES (?, ?, ?)')
.run(advertiserId, options.name || identifier, isDomain ? identifier : '');

const upsertAd = db.prepare(`
INSERT INTO ads (id, advertiser_id, format, content)
VALUES (?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
last_seen = datetime('now'),
is_active = 1,
days_running = CAST(
(julianday('now') - julianday(COALESCE(ads.first_seen, datetime('now')))) AS INTEGER
)
`
);

const tx = db.transaction(() => {
for (const ad of allAds) {
upsertAd.run(
ad.id || ad.creativeId || `gad_${Math.random().toString(36).slice(2)}`,
advertiserId,
ad.format || ad.adType || detectFormat(ad),
JSON.stringify({
headline: ad.headline || ad.title,
description: ad.description || ad.bodyText,
displayUrl: ad.displayUrl,
finalUrl: ad.finalUrl || ad.landingPage,
imageUrl: ad.imageUrl || ad.creative?.imageUrl,
})
);
}
});

tx();

return allAds;
}

function detectFormat(ad) {
if (ad.videoUrl || ad.video) return 'video';
if (ad.imageUrl && ad.headline) return 'display';
if (ad.headline && !ad.imageUrl) return 'search';
return 'unknown';
}









Step 5: Analyze Long-Running Winners



Same principle as Facebook ads — longevity = profitability:




function getWinningAds(advertiserId, minDays = 14) {
return db.prepare(`
SELECT *, json_extract(content, '$.headline') as headline,
json_extract(content, '$.description') as description,
json_extract(content, '$.finalUrl') as url
FROM ads
WHERE advertiser_id = ? AND days_running >= ?
ORDER BY days_running DESC
`
).all(advertiserId, minDays);
}

function printAdReport(advertiserId) {
const allAds = db.prepare(
'SELECT * FROM ads WHERE advertiser_id = ?'
).all(advertiserId);

const winners = getWinningAds(advertiserId, 14);

// Format breakdown
const formats = {};
allAds.forEach(ad => {
formats[ad.format] = (formats[ad.format] || 0) + 1;
});

console.log('📊 GOOGLE ADS INTELLIGENCE REPORT');
console.log(''.repeat(55));

console.log(`\n Total ads tracked: ${allAds.length}`);
console.log(` Long-running (14+ days): ${winners.length}`);
console.log(` Active: ${allAds.filter(a => a.is_active).length}`);

console.log('\n 📋 Format Breakdown:');
Object.entries(formats)
.sort((a, b) => b[1] - a[1])
.forEach(([format, count]) => {
const pct = ((count / allAds.length) * 100).toFixed(0);
console.log(` ${format}: ${count} (${pct}%)`);
});

if (winners.length > 0) {
console.log('\n🏆 WINNING ADS (14+ Days Running):');
console.log(''.repeat(55));

winners.slice(0, 10).forEach((ad, i) => {
console.log(`\n ${i + 1}. [${ad.days_running} days] ${ad.format.toUpperCase()}`);
if (ad.headline) console.log(` Headline: ${ad.headline}`);
if (ad.description) console.log(` Desc: ${ad.description?.substring(0, 100)}`);
if (ad.url) console.log(` URL: ${ad.url}`);
});
}
}









Step 6: AI-Powered Ad Copy Analysis






async function analyzeAdStrategy(advertiserId) {
const winners = getWinningAds(advertiserId, 7);

if (winners.length < 3) {
console.log('Need more data. Run spy first.');
return;
}

const adSample = winners.slice(0, 20).map(ad => ({
format: ad.format,
headline: ad.headline,
description: ad.description,
days: ad.days_running,
}));

console.log(`\n🧠 Analyzing ${adSample.length} ads with AI...\n`);

const completion = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{
role: 'user',
content: `Analyze this company's Google Ads strategy based on their longest-running ads.

Ads data:
${JSON.stringify(adSample, null, 2)}

Return JSON:
{
"overall_strategy": "2-3 sentence summary of their approach",
"target_audience": "who they're targeting based on ad copy",
"key_value_props": ["list of value propositions they emphasize"],
"headline_patterns": ["common headline formulas"],
"cta_patterns": ["call to action styles"],
"emotional_appeals": ["what emotions they target"],
"format_strategy": "how they use different ad formats",
"landing_page_strategy": "what their URLs reveal about funnel structure",
"weaknesses": ["potential gaps or weaknesses in their strategy"],
"counter_strategies": ["3 ways to compete against these ads"]
}`

}],
response_format: { type: 'json_object' }
});

const analysis = JSON.parse(completion.choices[0].message.content);

console.log('🎯 COMPETITIVE AD ANALYSIS');
console.log(''.repeat(55));

console.log(`\n📝 Strategy: ${analysis.overall_strategy}`);
console.log(`\n🎯 Target Audience: ${analysis.target_audience}`);

console.log('\n💎 Value Props:');
analysis.key_value_props.forEach(v => console.log(` • ${v}`));

console.log('\n📰 Headline Patterns:');
analysis.headline_patterns.forEach(h => console.log(` • ${h}`));

console.log('\n⚡ Counter-Strategies:');
analysis.counter_strategies.forEach((s, i) => console.log(` ${i+1}. ${s}`));

return analysis;
}









Step 7: Deep Dive on Individual Ads






async function inspectAd(adUrl) {
console.log(`🔎 Inspecting ad...`);

const { data } = await axios.get(
`${API_BASE}/v1/scrape/google-ad-library/ad-details`,
{ params: { url: adUrl }, headers }
);

const ad = data.data;

console.log('\n📋 AD DETAILS');
console.log(''.repeat(50));
console.log(` Advertiser: ${ad.advertiserName || ad.advertiser}`);
console.log(` Format: ${ad.format || ad.adType}`);
console.log(` Region: ${(ad.regions || ad.targetRegions || []).join(', ')}`);
console.log(` Last shown: ${ad.lastShown || ad.lastSeen}`);

if (ad.headline) console.log(`\n Headline: ${ad.headline}`);
if (ad.description) console.log(` Description: ${ad.description}`);
if (ad.displayUrl) console.log(` Display URL: ${ad.displayUrl}`);

return ad;
}









Step 8: CLI Interface






async function main() {
const command = process.argv[2];
const target = process.argv[3];

switch (command) {
case 'search':
await searchAdvertisers(target);
break;

case 'spy':
const advertisers = await searchAdvertisers(target);
if (advertisers.length > 0) {
const adv = advertisers[0];
const id = adv.id || adv.advertiserId;
await getCompanyAds(id, { name: adv.name });
printAdReport(id);
await analyzeAdStrategy(id);
}
break;

case 'domain':
await getCompanyAds(target);
printAdReport(target);
break;

case 'report':
printAdReport(target);
break;

case 'analyze':
await analyzeAdStrategy(target);
break;

case 'ad':
await inspectAd(target);
break;

default:
console.log('Google Ads Spy Tool\n');
console.log('Commands:');
console.log(' node spy.js search "Shopify" - Find an advertiser');
console.log(' node spy.js spy "Shopify" - Full intelligence report');
console.log(' node spy.js domain shopify.com - Spy by domain');
console.log(' node spy.js report <advertiserId> - Print stored report');
console.log(' node spy.js analyze <advertiserId> - AI strategy analysis');
console.log(' node spy.js ad <adUrl> - Inspect specific ad');
}
}

main().catch(console.error);









Running It






# Find a competitor
node spy.js search "Monday.com"

# Full spy analysis
node spy.js spy "Monday.com"

# Spy by domain directly
node spy.js domain monday.com









The Competitive Edge



Most companies check competitor ads once a quarter. With this tool, you can:





  1. Daily monitoring: See new ads within hours of launch


  2. Pattern detection: Know exactly what copy formulas work for them


  3. Counter-positioning: Build ads that directly counter their messaging


  4. Budget estimation: More ad variations = larger budget



Everyone's landing pages are different, but their ad copy tells you exactly what converts.






Cost Comparison

































Tool Price Scope
Semrush Ad Research $129/mo Google ads + estimates
SpyFu $39/mo Historical data, limited current
iSpionage $59/mo Google + Bing
This tool ~$0.05/spy session Full data + AI analysis





Get Started




  1. Get your API key at sociavault.com

  2. Search for your biggest competitor

  3. See exactly what they're spending money on



Their ad playbook isn't a secret. It's sitting in the Google Ad Library. We're just reading it faster.






The best ad strategy starts with knowing what already works. Your competitors already ran the experiments for you.






javascript #googleads #marketing #webdev

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Build a Google Ads Competitor Intelligence Tool with Node.js

Thematisch verwandte Begriffe: Build, Google, Competitor, Intelligence · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-75517 | Novu provides an API for sending notifications through multiple channels…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick