adlibrary.com Logoadlibrary.com
Share
Competitive Research,  Guides & Tutorials

Cross-Platform Ad Tracking: Competitor Ads in One Pipeline

Competitors think in campaigns, not platforms. This pipeline resolves a brand to advertiser IDs, fans one curate call out across Meta, Google, and LinkedIn, and builds the unified timeline their separate ad libraries can never show you.

Cross-platform ad tracking pipeline dashboard unifying Meta, Google, and LinkedIn competitor ads

A competitor running Meta, Google, and LinkedIn at the same time is not running three strategies. They planned one campaign, briefed one creative team, and adapted the output for each network. Cross-platform ad tracking exists because the platform-by-platform view hides exactly that. Check three ad libraries separately and you get three disconnected fragments. The campaign, the thing you actually want to read, never appears on any single screen.

TL;DR: Competitors think in campaigns, not platforms. Tracking each ad library separately means you reconstruct their strategy by hand, every week. One pipeline does the reconstruction for you: resolve the brand to advertiser IDs (free), save it once with IDs per platform, then a single curate call fans out to Meta, Google, and LinkedIn in parallel, dedups by ad key, and feeds a unified timeline you can report from. You can build it in an afternoon on the AdLibrary API.

This guide walks through that pipeline end to end, with working calls at every stage. It is written for the strategist covering a competitor who runs Meta plus Google plus LinkedIn simultaneously, because that is where the per-platform approach breaks first.

Why per-platform tracking fragments the competitive picture

The manual version of cross-platform ad tracking looks like this. Open Meta's Ad Library, search the brand, and screenshot whatever scrolls past. Open the Google Ads Transparency Center, repeat with a different search syntax and a different advertiser identity. Open the LinkedIn Ad Library, repeat again. Paste everything into a deck and hope the three snapshots line up.

They never line up, for three structural reasons.

Timing signals get severed. A competitor's typical launch sequence is staggered. Video tests on Meta first, the survivors graduate to YouTube, and the proven message lands on LinkedIn three weeks later as a single-image ad. Each library shows you one frame of that motion. None shows you the sequence, and the sequence is the strategy.

Identity fragments. The same company is a numeric page ID on Meta, an AR-prefixed advertiser ID in Google's transparency data, and a numeric company ID on LinkedIn. Big brands multiply the problem by running several accounts per platform. Match them by eye and you will miss sub-brands and regional pages, which is where tests usually hide.

Effort scales linearly with platforms. Three platforms, ten competitors, weekly cadence. That is thirty manual research sessions a week before you have written a single insight. Most teams quietly drop to monthly checks, then the competitive intelligence function decays into screenshots of whatever someone happened to notice.

The transparency surfaces themselves are genuinely good and worth knowing. The EU's Digital Services Act is the reason every major platform now maintains a public ad repository at all. Meta's free Ad Library API is the original and still the reference point for single-platform research. But it covers Meta, and its programmatic access is scoped to political and social-issue ads in most regions, behind an app review and tokens that expire every 60 days, per Meta's own documentation. LinkedIn's programmatic surface lives in the Marketing API on Microsoft Learn and solves a different problem entirely, managing your own campaigns rather than reading competitors'.

Meta's free API is fine for one platform. The moment you need Google and LinkedIn data in the same query, you need a different layer. That layer is what the rest of this article builds.

What cross-platform ad tracking looks like as one pipeline

The pipeline has five stages, and only two of them cost credits.

StageCallCost
1. Resolve brand to IDsGET /api/advertisers/searchFree
2. Save the advertiserPOST /api/advertisersFree
3. Fan out across platformsPOST /api/advertisers/{id}/curate1 credit per 30-min session
4. Dedup + timelineYour own store, keyed by ad_keyFree
5. ReportYour template over the storeFree

Stage 1 is the step most teams skip, and skipping it is why their tracking breaks. Treat ID resolution as Step 0 of any competitor workflow: until a brand name is pinned to concrete platform IDs, every downstream query is a guess. The unified ad search behind the AdLibrary API covers Facebook, Instagram, TikTok, YouTube, Google, LinkedIn, Twitter, Pinterest and more, but for a tracking pipeline you want the saved-advertiser route rather than repeated keyword searches. Keyword search costs 1 credit per page and answers "who is advertising in this space." Saved advertisers answer "what is this specific competitor doing," which is the tracking question.

Authentication is one header. Keys start with adl_, are created in the dashboard on the Business plan, and you can hold up to 10 of them, one per client or environment. No app review and no 60-day token babysitting. If you want the full surface area first, the API documentation walkthrough covers every endpoint in depth.

Step 0: resolve the brand to advertiser IDs on every platform

One free call turns a brand name into the per-platform IDs everything else needs:

bash
curl -G "https://adlibrary.com/api/advertisers/search" \
  -H "Authorization: Bearer adl_your_api_key" \
  --data-urlencode "q=gymshark" \
  --data-urlencode "country=US" \
  --data-urlencode "limit=10"

The response fans out to Meta, Google, and LinkedIn in parallel and comes back with a best_match plus per-platform candidate lists:

json
{
  "query": "gymshark",
  "country": "US",
  "best_match": {
    "name": "Gymshark",
    "confidence": 1.0,
    "meta":     { "id": "123456789", "name": "Gymshark", "verified": true },
    "google":   { "id": "AR01234567890123456789", "name": "Gymshark", "ad_count": 412 },
    "linkedin": { "id": "2631261", "name": "Gymshark", "ad_count": 38 }
  },
  "candidates": { "meta": [], "google": [], "linkedin": [] }
}

Two details matter here. First, best_match only appears when at least two platforms agree on the normalized brand name, and confidence reflects how many of the three agreed. A 0.66 means two platforms matched. Treat that as a prompt to eyeball the third platform's candidates manually rather than trusting the merge blind.

Second, scan the candidates arrays even when best_match looks clean. This is where you catch the sub-brand accounts. A brand like Nike resolves to Nike, Nike Football, Nike Run Club and more, each a separate Meta page with its own ads. A tracking pipeline that only follows the flagship page reports "no new activity" while the competitor scales a campaign through a sibling account. The competitor ad lookup workflow goes deeper on resolving messy brand portfolios.

Collect every ID that genuinely belongs to the competitor. The next stage stores them all in one record.

Save the advertiser once, with IDs per platform

A saved advertiser is the persistent object your pipeline revolves around. It holds all of a brand's accounts across platforms behind one UUID:

bash
curl -X POST "https://adlibrary.com/api/advertisers" \
  -H "Authorization: Bearer adl_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Gymshark",
    "domain": "gymshark.com",
    "meta_page_ids": ["123456789", "987654321"],
    "google_advertiser_ids": ["AR01234567890123456789"],
    "linkedin_company_ids": ["2631261"]
  }'

The call is free and returns 201 with the saved record, including the id you will use for every curate call from now on. Each ID field accepts a single string or an array, and at least one platform array must be non-empty. When you discover a new sub-brand page next quarter, a PATCH to /api/advertisers/{id} adds it without touching the rest of the record, and the pipeline picks it up on the next pull automatically.

This is the same mechanism behind the saved ads and advertiser-tracking features in the AdLibrary app, exposed as plain REST. Build the roster once: every competitor your team covers, saved with every ID you resolved in Step 0. For an agency, that roster maps one-to-one onto the client book, and the agency reporting system you already run can consume what comes out the other end.

Curate: one call that fans out to every platform

Here is the call that replaces the thirty manual sessions:

bash
curl -X POST "https://adlibrary.com/api/advertisers/<uuid>/curate" \
  -H "Authorization: Bearer adl_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{}'

One request. The server queries every saved Meta page ID, Google advertiser ID, and LinkedIn company ID in parallel and returns a per-platform block:

json
{
  "meta":     { "sources": [{"id": "123456789", "name": "Gymshark", "count": 214}],
                "ads": ["..."], "cursors": { "123456789": "opaque-cursor" } },
  "google":   { "sources": ["..."], "ads": ["..."], "cursors": {} },
  "linkedin": { "sources": ["..."], "ads": ["..."], "cursors": { "2631261": "2" } },
  "credits":  { "used": 1, "remaining": 999 }
}

The billing model rewards exactly the behavior a tracking pipeline wants. The first curate call for an advertiser opens a 30-minute session and costs 1 credit. Every continuation within that window is free, as long as you pass back the cursors from the previous response:

bash
curl -X POST "https://adlibrary.com/api/advertisers/<uuid>/curate?platform=meta" \
  -H "Authorization: Bearer adl_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"cursors": {"meta": {"123456789": "opaque-cursor"}}}'

So a full pull of a competitor's recent ads across all platforms, paginated to exhaustion, is 1 credit total if you finish within the session. Practical notes from running this in production:

  • Pages are 25 ads everywhere. LinkedIn caps at 25 per response, so the API normalizes all platforms to that page size. A null cursor means that source is exhausted.
  • LinkedIn cursors are page numbers as strings. Don't parse meaning into them. Pass them back verbatim like any other cursor.
  • sources arrives only on the first call of a session. Cache it if your tooling needs the per-account ad counts.
  • Google requires Pro or Business tier. On lower tiers the google block comes back empty with a note explaining why. Since API keys are Business-only anyway, a key-based pipeline always gets the Google block.
  • One curate at a time per advertiser. A concurrent first call returns 409 with a retry hint. Serialize your roster loop instead of blasting all competitors at once, which also keeps you inside the 10-requests-per-minute key limit.

If your competitor is LinkedIn-heavy, the LinkedIn ad library alternative guide covers the quirks of that platform's data in more detail. For the wider context of searching many networks at once, see the multi-platform ad library search guide.

Ad deduplication unified timeline showing cross-platform competitor ad tracking sorted by ad key

Dedup by ad key and build the unified timeline

Every ad in a curate response carries an ad_key, a platform-prefixed stable identifier: meta_<id>, google_<creativeId>, linkedin_<urn>. Within one platform block the API has already deduped across the advertiser's multiple accounts. Your job is the cross-pull dedup: the same ad_key showing up in Monday's pull and Thursday's pull is one ad observed twice, and that second observation is signal, because it updates the ad's lifespan.

The store can be a single table. Key on ad_key, insert on first sight, update last_seen on every re-observation:

python
import requests, time

API = "https://adlibrary.com/api"
H = {"Authorization": "Bearer adl_your_api_key"}

def pull_all(advertiser_uuid):
    ads, cursors, first = [], None, True
    while True:
        body = {"cursors": cursors} if cursors else {}
        r = requests.post(f"{API}/advertisers/{advertiser_uuid}/curate",
                          headers=H, json=body).json()
        nxt = {}
        for platform in ("meta", "google", "linkedin"):
            block = r.get(platform, {})
            ads += [{**ad, "platform_block": platform} for ad in block.get("ads", [])]
            live = {k: v for k, v in block.get("cursors", {}).items() if v}
            if live: nxt[platform] = live
        if not nxt: return ads
        cursors, first = nxt, False
        time.sleep(7)  # stay under 10 req/min

def upsert(db, ads, observed_at):
    for ad in ads:
        row = db.get(ad["ad_key"])
        if row is None:
            db[ad["ad_key"]] = {
                "ad_key": ad["ad_key"], "platform": ad["platform_block"],
                "first_seen": ad.get("first_seen"), "last_seen": ad.get("last_seen"),
                "ads_type": ad.get("ads_type"), "message": ad.get("message"),
                "first_observed": observed_at, "last_observed": observed_at,
            }
        else:
            row["last_observed"] = observed_at
            row["last_seen"] = ad.get("last_seen") or row["last_seen"]

Three derived events fall out of this store for free, and they are the entire tracking product:

  1. Launch: an ad_key you have never seen. New creative is in market.
  2. Retirement: an ad_key absent from pulls for N consecutive days (7 is a sane default). The competitor killed it, which is as informative as a launch. Ads that die in week one failed their test.
  3. Endurance: last_seen minus first_seen keeps growing. Long-running ads are the competitor's proven winners, the same runtime logic the ad timeline view applies inside the app.

Sort the store by first_seen and you have the unified timeline: every creative the competitor launched, on any platform, in one ordered stream. The staggered rollout that was invisible across three separate libraries is now just rows appearing in sequence. Meta video on March 3, YouTube cut of the same concept March 18, LinkedIn static April 2. You are no longer reconstructing the campaign. You are reading it.

This is also the foundation for alerting. Diff today's pull against the store and pipe new ad_keys to Slack. The competitor ad monitoring playbook covers diff-detection and alert design, and the n8n recipe collection shows the same loop as a no-code workflow if Python is not your stack. Agents work too: the Claude Code workflow guide runs this exact pipeline conversationally, and you can wrap it as a tool server with the MCP server tutorial.

Spotting platform-specific creative adaptation

The timeline tells you when. The creative fields tell you how the competitor adapts one campaign per platform, and this is where cross-platform ad tracking earns its keep for a strategist.

Group your stored ads by campaign concept first. Landing page URL is the most reliable grouping key, since platform variants of one campaign usually funnel to the same destination. Message similarity works as a fallback. Within each concept group, compare across platforms on three axes:

Format shifts. The ads_type field codes the creative format: 1 image, 2 video, 3 carousel, 4 collection. A pattern you will see constantly: UGC-style video on Meta, a tighter cut on YouTube, and a single static image with a stat overlay on LinkedIn. Same concept, three formats. When a competitor does NOT adapt and just reruns the Meta vertical video on LinkedIn, that is also signal. It usually means the platform is an afterthought in their media plan.

Message shifts. Compare the message and title fields across the group. Watch the creative angle mutate: price-led on Meta, proof-led on LinkedIn, where the audience is colder and the CPMs punish weak relevance. The hook often survives translation while the body copy gets rewritten entirely for a B2B register.

Cadence shifts. Compute per-platform refresh cadence from your launch events. Most multi-platform advertisers refresh Meta creative on a 2-4 week cycle and let LinkedIn creatives run for months. When the LinkedIn cadence suddenly accelerates, budget or attention moved there. You will see it in the timeline weeks before it shows up anywhere else.

For the ads that matter, one enrichment call per creative returns the deep read: a scene-by-scene transcript, the strategic teardown of hook, offer and proof, and a replication brief you can hand to your own creative team. That costs 1 credit per ad, so reserve it for the winners your runtime data has already flagged rather than enriching everything. The competitor-ad-to-campaign pipeline shows how far that loop can go.

The cross-platform ad tracking report template

Raw timelines impress nobody. The report does. Here is a weekly template that turns the store into something a CMO reads, structured so every section is a query over the table you built above.

1. Movement summary (the headline). Launches, retirements, and net active count per platform, week over week. One sentence of interpretation: "Competitor X launched 9 new Meta creatives and retired 11, while LinkedIn held steady. Heavy testing, no winner yet."

2. New concepts. New ad_keys grouped by landing page, with preview image, platform, format, and opening copy. Flag concepts appearing on multiple platforms in week one, because synchronized launches mean conviction backed by budget.

3. Proven winners. The 5 longest-running active ads per competitor. Runtime is the cleanest public proxy for performance, since paid duds get killed fast. Note format and angle for each.

4. Adaptation read. For one or two concept groups, the per-platform comparison from the previous section. This is the part of the report only cross-platform ad tracking can produce, and the part strategists get rehired for.

5. Pressure indicators. Direction, never precision. Impressions come back as bucketed ranges, and spend figures are always estimates, so report movement ("impression buckets shifted up two bands on the Meta flagship") rather than fake-precise numbers. If you need to translate activity into budget language for a client conversation, run the creative volume through the ad spend estimator and frame the output as a modeled range. The competitive spending report guide covers defensible spend narratives in depth.

6. Recommended responses. Tie each observation to an action, whether that is a creative brief to commission or a budget reallocation to model in the media mix modeler. A tracking report without a recommendation column is trivia.

Two honesty rules keep the report credible. Quote ranges as ranges. And date every claim with the pull timestamp, since ad libraries lag reality by hours to days. If you are evaluating tooling around this workflow more broadly, the tracking platform rubric compares the options on exactly these reporting capabilities.

What the pipeline costs to run

The math is short. Curate is 1 credit per advertiser per session, and pagination inside the 30-minute window is free.

  • 10 competitors, daily pulls: 10 credits/day, roughly 300/month.
  • Enrichment of flagged winners: maybe 20-40 ads/month at 1 credit each.
  • Occasional keyword sweeps for new entrants (each search costs 1 credit per page and returns a total count you can use for market sizing): another 20-50.

Call it 350-400 credits a month for a serious ten-competitor practice. The Business plan at €329/mo includes 1000+ credits plus API access, so the pipeline runs at a third of the allowance with room for ad-hoc research on top. Rate limits are 10 requests per minute and 10,000 per day per key, generous enough that a sequential roster loop never feels them. Failed searches refund their credit automatically.

Compare that against the labor it replaces. Thirty manual research sessions a week at even 20 minutes each is 40+ hours a month of strategist time spent collecting instead of interpreting. The pipeline collapses collection to a cron job and returns those hours to the analysis layer, which is the only layer clients actually pay for. Automation-first teams can wire the whole thing through the automated competitor monitoring pattern, and the broader cross-platform strategy use case shows how the same data feeds planning beyond competitive work.

Frequently Asked Questions

What is cross-platform ad tracking?

Cross-platform ad tracking is the practice of monitoring a competitor's advertising across multiple networks (Meta, Google, YouTube, LinkedIn and others) in one unified workflow, rather than checking each platform's ad library separately. The goal is to see campaigns the way the competitor planned them: one strategy adapted per platform, on one timeline.

Can I track competitor ads across Meta, Google, and LinkedIn with one API call?

Yes. With the AdLibrary API you resolve the brand to per-platform advertiser IDs with a free lookup, save them as one advertiser record, then a single curate call fans out to Meta, Google, and LinkedIn in parallel and returns deduplicated ads per platform with pagination cursors. One credit covers a full 30-minute pull session per advertiser.

How does deduplication work across platforms?

Every ad carries a stable, platform-prefixed ad_key (for example meta_123, google_456, linkedin_789). Within a platform, the API dedups across the advertiser's multiple accounts automatically. Across pulls, you upsert on ad_key in your own store, so repeated observations update an ad's lifespan instead of creating duplicates.

How much does it cost to track 10 competitors across platforms?

Daily curate pulls for 10 saved advertisers cost about 300 credits per month, since each advertiser's session costs 1 credit regardless of how many platforms and pages it spans. With selective AI enrichment and ad-hoc searches, a realistic total is 350-400 credits. The Business plan (€329/mo) includes 1000+ credits and API access.

Is Meta's free Ad Library API enough for cross-platform tracking?

No, by design. Meta's Ad Library API is free and authoritative for Meta, but it covers only Meta platforms, its programmatic scope is limited mostly to political and social-issue ads, and access requires app review plus tokens that expire every 60 days. For commercial ads across Meta, Google, LinkedIn, TikTok and more in one pipeline, you need a multi-platform layer on top.

One pipeline, one picture

The per-platform habit persists because each ad library is individually decent. Decent is the trap. Three decent fragments still leave the actual object of study, the campaign, for you to reassemble by hand every single week.

Cross-platform ad tracking through one pipeline inverts the work. Resolve once, save once, curate on a schedule, and the unified timeline assembles itself, with the per-platform adaptations sitting side by side where a strategist can actually read them. The build is an afternoon: two free endpoints, one paid call, and a table keyed on ad_key.

API access ships with the Business plan at €329/mo, which includes the 1000+ monthly credits this pipeline needs several times over, plus integration help from the team if you want a second pair of eyes on your loop. Grab a key from the API access page, run the free resolver on your loudest competitor, and look at the timeline it produces. Their campaign was never three separate stories. Now your tracking isn't either.

Related Articles

Media buying software category matrix showing seven vertical lanes for DSP, Meta-optimizer, creative production, attribution, bid automation, competitive research, and MMM tools
Platforms & Tools,  Competitive Research

Best Competitor Ad Tracking Platforms 2026

The best competitor ad tracking platforms in 2026 compared by platform coverage, creative depth, timeline quality, and API access. A practical decision guide for media buyers.