---
name: "competitor_ad_library_analysis"
description: "Read competitor ads from public ad libraries only, with no ad account needed: collect live ads from Meta, Google, TikTok, LinkedIn and Microsoft libraries, code each ad for format, hook, angle, offer and CTA, spot positioning gaps, and turn the pattern into test briefs for your own creative. Ships an ad coding sheet, a gap worksheet, and worked teardowns. Triggers on 'what ads are competitors running', 'check the Meta Ad Library for X', 'ad library teardown', 'competitor ad research', or 'find a gap in competitor ads'."
---

# Competitor Ad Library Analysis

## Purpose

Turn public ad libraries into a coded, comparable picture of what competitors are paying to say right now, and where they are all saying the same thing.

Scope is library-only and account-free. You work from what Meta, Google, TikTok, LinkedIn, and Microsoft publish for anyone to see. You never need a competitor's ad account, a paid spy tool, or login credentials for a library. If a fact is not in a public library, it is not in this analysis.

This is different from a social audit. A social audit reads organic posts. This skill reads paid ads, which carry a stronger signal: a brand chose to spend money behind that exact message, format, and offer.

## Workflow

### Step 1: Frame the job

Collect these before you open a library:

- Your brand and the claim you want to test, in one sentence. Example: we are faster to set up than the category.
- Three to five competitors. More than five makes coding slow and gaps hard to read.
- One market: country and, where it matters, region. Libraries filter by where an ad was served, and mixing markets mixes messages written for different buyers.
- One window: usually the last 30 to 90 days, plus any ad still active regardless of start date.
- The libraries that fit the category. B2C social categories start with Meta and TikTok. Search and YouTube categories start with Google. B2B starts with LinkedIn and Google. Check the other libraries before you call a competitor inactive.

Write the frame at the top of the gap worksheet in `assets/gap-worksheet.md`. A teardown without a frame becomes a screenshot pile.

### Step 2: Find the right advertiser, not just the right name

Search each library the way that library actually works. Full detail, coverage, and retention per library live in `references/library-map.md`. Read it before your first pull.

- Meta Ad Library, at facebook.com/ads/library: search by Page name, Page ID, or keyword. Filter by country, platform, and ad type set to All ads for commercial research.
- Google Ads Transparency Center, at adstransparency.google.com: search by domain first, not by brand name. Big brands advertise under legal entity names and per-country accounts, so a name search can return the wrong entity and a thin result set. Confirm the verified advertiser profile matches the brand before coding a single ad.
- TikTok: keep the two tools separate. The Commercial Content Library at library.tiktok.com covers ads served in the EEA, Switzerland, and the UK, and does not cover US ads. Creative Center Top Ads at ads.tiktok.com/business/creativecenter covers curated high performers globally, filtered by region, industry, and objective. Use the first for a named brand in Europe, the second for category winners.
- LinkedIn Ad Library, at linkedin.com/ad-library: search by company, payer, or keyword, filtered by country and date. It covers ads from June 1, 2023, kept for one year after the last impression.
- Microsoft Ad Library, at adlibrary.ads.microsoft.com: check it when search ads on Bing matter, with the strongest detail for EU and EEA served ads.

If a competitor returns nothing, check the parent company, other brand names they operate under, their domain in Google, and a second region before you record anything. An empty result is a lead to check, not a finding. Record a true empty result as: searched, libraries checked, entities checked, date.

### Step 3: Collect a clean sample

Pull ads per competitor per library until one of these stops you:

- You have 20 to 30 ads for that competitor, or all active ads if they run fewer.
- New ads stop adding new angles, hooks, or offers. The last five ads repeated codes you already have.

For every ad, save the library link, a screenshot or the creative file name, the full primary text and headline, the landing page URL, the start date, and whether it was still active at capture. Save the capture date with everything. Libraries with short retention lose ads fast, and Google results in particular can age out in about 30 days after last serving according to secondary guides, so capture first and code second.

Do not cherry-pick the ads that look weak or strong. Code the full sample you pulled, or state the sampling rule you used, such as newest 25 or all video ads.

### Step 4: Code every ad

Code each ad on the coding sheet in `assets/ad-coding-sheet.csv`. One row per ad, one code per field, no free-text synonyms. The full codebook, with definitions and tie-break rules, is in `references/coding-taxonomy.md`. The fields are:

- Format: image, video, carousel, text, document, shopping, other
- Hook type: question, problem, claim, proof, story, offer-led, comparison, demo, other
- Angle: the main reason to buy in that ad, such as speed, price, ease, quality, status, risk removal, or a named category angle you add to the codebook before coding starts
- Promise: the outcome the ad promises, in five words or fewer
- Proof: none, testimonial, number, demo, credential, guarantee, other
- Offer: none, discount, free trial, free resource, demo call, bundle, free shipping, other
- CTA: the button or closing line exactly as shown, normalised to the codebook list
- Longevity: start date, last seen date, and days running

Code what the ad says, not what you think the brand meant. If two codes fit, use the tie-break in the codebook: code the first three seconds or the headline, whichever a viewer meets first.

Have a second pass on at least 20 percent of rows when a second person or a second run is available. Where the two passes disagree, fix the codebook wording, not just the row. Disagreement usually means the definition was loose.

### Step 5: Run the numbers

Run the coding sheet through the analyser:

```
python3 bin/code_ads.py assets/ad-coding-sheet.csv --out report.md
```

It prints per competitor: ad count by library and format, hook and angle mix as percentages, offer and CTA mix, median and longest days running, and the count and share of ads running 30 days or more and 90 days or more. It also prints category saturation (angles, offers, and formats almost everyone uses) and per competitor gaps (angles and offers used by at least two rivals that this competitor never uses).

Treat longevity with care. No commercial library here publishes spend, clicks, or conversions, so a long-running ad is an inference: brands usually stop paying for ads that do nothing, so an ad active for 90 days is more likely to be working than an ad killed in three days. Write it that way, as a likely signal, never as proof of performance. Variant count carries a similar signal: many live variants of one angle means the brand is investing in testing that angle.

### Step 6: Find the gaps

Fill in `assets/gap-worksheet.md`. A gap only counts if it passes all three tests:

- Real: at most one competitor in the sample codes into it, checked in the analyser output, not from memory.
- Credible for your brand: you have a product fact, proof point, or asset that can support the claim. A gap you cannot back is a trap, not an opening.
- Worth reaching: the buyer in this market plausibly cares. Check it against reviews, sales calls, or search language when you can, and say what you checked.

Sort gaps into three kinds and label each one:

- Message gap: an angle or promise nobody is making.
- Offer gap: a way of starting (trial length, guarantee, bundle, free resource) nobody is offering in ads.
- Format or hook gap: a format or opening style the category ignores, such as demo-first video where everyone leads with a static claim.

Also record crowded ground: angles used by 75 percent or more of competitors. Crowded does not mean forbidden, it means a new ad there has to beat several proven ads head on, and the brief should say why it can.

Worked examples of this whole pass, including the domain-search pitfall and the TikTok two-tool trap, are in `references/worked-teardowns.md`. Read them before your first real teardown.

### Step 7: Turn gaps into test briefs

Write one brief per gap worth testing, using `assets/test-brief-template.md`. Each brief states:

- The gap it attacks, with the counts from the coding sheet that prove the gap
- One hypothesis in plain form: buyers in this market will respond to X because no competitor offers it and Y supports it
- The hook, angle, proof, offer, and CTA to test, kept distinct from competitor wording
- Two or three variants maximum for the first test, and what stays constant across them
- The landing page the ad points to, and a check that the page says the same thing as the ad
- A kill and keep rule written before launch, such as a minimum spend or time window and the metric that decides

Briefs borrow the structure of what works in the category, such as a proven format or hook shape. They never copy a competitor's copy, creative, claims, or brand assets.

## Output Contract

- One filled coding sheet as CSV, one row per ad, with library links and capture dates, so anyone can re-check every code against the source ad.
- One analyser report from `bin/code_ads.py`, pasted or attached, with counts, mixes, longevity, saturation, and gaps.
- One filled gap worksheet with each gap labelled message, offer, or format/hook, and each gap passing the real, credible, and worth-reaching tests with the evidence named.
- One to three test briefs, each tied to a named gap and a written kill and keep rule.
- A limits line at the end of every deliverable stating what the libraries do not show for this sample: no spend, no targeting for most commercial ads, no clicks or conversions.

## Operating Rules

1. Public library data only. No logged-in scraping of someone else's account, no leaked dashboards, no paid spy tool output presented as library fact. If a tool estimates spend, label it an estimate with the tool named.
2. Never claim spend, performance, or targeting that the library did not publish. EU-served ads on some libraries publish reach ranges and targeting parameters, and political ads publish more. Ordinary commercial ads on Meta, Google, LinkedIn, and Microsoft do not publish spend or clicks. Say which case your sample is in.
3. Domain first on Google, entity check everywhere. A wrong advertiser profile poisons the whole sheet. Verify the verified name, the domain, and the region before coding.
4. Longevity and variant count are inferences, not results. Phrase them as likely signals and keep them out of any sentence that states a competitor's returns.
5. Empty is a result only after the checks. Parent, brand names, domain, and a second library or region get checked before a competitor is recorded as not advertising there.
6. Dates on everything. Record capture date, start date, and last seen date per ad. A count without a capture date cannot be compared with the next pull.
7. Same market, same window, same codebook for every competitor in one teardown. Changing any of the three mid-sample makes the mixes incomparable.
8. Do not copy competitor creative. Learn the pattern, write your own. No competitor copy, images, video, or claims pass into a brief except as a short quoted example inside the internal teardown, clearly attributed to its source ad.
9. No invented numbers. If a library field was blank or a reach range was not published for an ad, leave the cell blank and note the gap. Never fill a missing value with a guess.
