---
name: impressions-spy
description: Activates when the user asks to research competitor ads, find what's working in their niche, run a competitive intelligence scan, or identify winning ad patterns from the Meta Ad Library. Uses Meta's Ad Library API combined with the impression-volume sorting feature (added Q1 2026) to identify which competitor ads are actually scaling vs. just running. Generates a weekly report with new winners, scaling ads, killed ads, and pattern insights.
---

# Impressions Spy Skill

The competitive intelligence layer of Pillar 5. Replaces hours of manually browsing the Meta Ad Library with an automated weekly research report. Identifies which competitor ads are scaling (high impressions + long runtime), spots cross-brand pattern convergence, and outputs a creative brief informed by what the market is already validating.

## Activation Rules

Activate when:
- The user asks to "spy on competitors," "research what's working," "find winning ads," or "run competitive intelligence"
- The user runs the `/impressions-spy` slash command
- A scheduled cron job triggers the weekly research run

## Prerequisites

1. **A Meta Developer account** at developers.facebook.com (free)
2. **An Ad Library API access token** (free, generated through the Meta developer portal)
3. **A list of competitor brand names + Facebook Page IDs** (see Configuration section below)
4. **brand-kit.md** in project root (used for context on which patterns are most relevant)

If the API token isn't configured, prompt the user to set it up before continuing.

---

## Configuration

This skill maintains a competitor list at `./config/competitors.json`. Format:

```json
{
  "country": "US",
  "competitors": [
    {
      "brand_name": "Brand One",
      "page_id": "123456789012345",
      "category": "supplements",
      "notes": "Direct competitor, similar price point"
    },
    {
      "brand_name": "Brand Two",
      "page_id": "234567890123456",
      "category": "supplements",
      "notes": "Larger budget, watch for scaling moves"
    }
  ],
  "thresholds": {
    "high_impression_minimum": "100K",
    "long_runtime_days": 60,
    "scaling_signal_jump": "1_bucket"
  }
}
```

**How to find a competitor's Page ID:**

1. Go to the brand's Facebook page
2. Click "About"
3. Scroll to "Page transparency"
4. Page ID is listed there

Alternatively, use the Ad Library search and grab the `page_id` from the URL after clicking on a brand.

---

## Slash Commands

### `/impressions-spy`

The primary command. Runs the full weekly research workflow.

**Workflow:**

1. **Read competitor list** from `./config/competitors.json`

2. **For each competitor**, query the Meta Ad Library API:
   ```
   GET https://graph.facebook.com/v18.0/ads_archive
   Parameters:
     - search_page_ids: [page_id]
     - ad_active_status: ACTIVE
     - ad_reached_countries: [country]
     - access_token: [your token]
     - fields: ad_creative_bodies, ad_creative_link_titles, 
              ad_creative_link_descriptions, ad_delivery_start_time,
              ad_snapshot_url, page_name, publisher_platforms
     - limit: 100
   ```

3. **Filter results** to only ads with high-impression indicators (the API returns impression ranges, not exact numbers). Keep ads in the `100K-1M` and `1M+` buckets.

4. **For each high-impression ad**, extract:
   - Hook (first sentence of ad copy)
   - Headline (link title)
   - Format (image / video / carousel — inferred from creative type)
   - Start date and days active
   - Destination URL
   - Impression range bucket
   - Platform mix (Facebook only, Instagram only, both, etc.)

5. **Compare to last week's data** (stored at `./data/spy-history-[date].json`):
   - **NEW** high-impression ads (didn't exist last week)
   - **SCALING** ads (moved up at least one impression bucket)
   - **DISAPPEARED** ads (were high-impression last week, now gone — likely killed)

6. **Run pattern analysis** across all high-impression ads:
   - Hook convergence (which hook patterns appear across multiple competitors)
   - Format convergence (which formats are getting the most distribution)
   - Offer convergence (which offer structures appear across competitors)
   - Untested gaps (angles no one is running)

7. **Generate the weekly report** with these sections:
   - **A. Executive Summary** — 3 sentences: biggest moves, top pattern, recommended action
   - **B. New high-impression ads this week** — table with brand, hook, format, days active, impression range, destination URL
   - **C. Scaling ads** — ads that moved up in impression range
   - **D. Killed ads** — ads that disappeared since last week (signals what's NOT working)
   - **E. Pattern analysis** — convergences and gaps
   - **F. Creative brief for next batch** — top 3 angles to test based on this week's data

8. **Save outputs:**
   - Report: `./reports/spy-report-[date].md`
   - Raw data: `./data/spy-raw-[date].json` (for week-over-week comparison)

### `/impressions-spy --competitor [brand_name]`

Deep-dive on a single competitor.

**Usage:**
```
/impressions-spy --competitor "Brand One"
```

**Returns:** Full ad inventory for that competitor, sorted by impression range, with pattern analysis specific to that brand.

### `/impressions-spy --since [date]`

Compare current state vs. a specific previous date.

**Usage:**
```
/impressions-spy --since 2026-07-01
```

**Returns:** Diff report showing what's new, scaled, killed since the specified date. Useful for monthly reviews instead of just weekly.

### `/add-competitor [page_id] [name]`

Add a competitor to the tracking list.

**Usage:**
```
/add-competitor 123456789012345 "New Competitor"
```

The skill will prompt for category and notes interactively.

### `/list-competitors`

Show the current competitor list.

### `/feed-to-strategist`

Take this week's spy report findings and convert them into a creative brief for Pillar 1's static-ad-designer.

**Workflow:**
1. Read the most recent spy report
2. Extract the top 3 hook patterns and top 3 untested gaps
3. Generate a creative brief in the format expected by `/build-matrix-from-strategy`
4. Save to `./creative-brief-from-spy-[date].md`
5. Suggest next steps to chain into static-ad-designer

This is the strategic compounding move: research → strategy → production → distribution → analysis → loop.

---

## The 60-Day Rule (Built Into the Analysis)

Not all high-impression ads are confirmed winners. The skill applies the 60-day longevity rule:

| Days active | Confidence level | Recommendation |
|---|---|---|
| 0-14 | Low — still testing | Watch but don't reverse-engineer yet |
| 14-30 | Medium — likely performing | Note the pattern, watch next week |
| 30-60 | High — very likely profitable | Start reverse-engineering |
| 60+ | Near-certain | Reverse-engineer immediately |

The skill flags every high-impression ad with its confidence tier. Reports show:

```
⭐ CONFIRMED WINNER (60+ days, 100K-1M impressions)
✓ HIGH CONFIDENCE (30-60 days, 100K-1M impressions)
~ MEDIUM CONFIDENCE (14-30 days, 100K-1M impressions)
? EARLY TEST (0-14 days, 100K-1M impressions)
```

Focus reverse-engineering effort on ⭐ and ✓ ads. Use ~ and ? ads as leading indicators of what to watch next week.

---

## Cross-Skill Integration

**Calls into this skill:**
- The user (directly)
- Scheduled cron job (every Monday morning)
- The static-ad-designer skill (when building a matrix from competitor research)

**This skill calls:**
- The Meta Ad Library API (free, no MCP needed — direct HTTP calls)
- brand-kit (for context on what patterns are relevant to the user's category)

**Output flows to:**
- The user (weekly report)
- creative-strategist or static-ad-designer (via `/feed-to-strategist`)
- advertorial-builder (Pillar 4) — when a competitor advertorial URL is identified, pass it to advertorial-builder for reverse-engineering

---

## Common Issues

### "I'm hitting API rate limits"

Meta's Ad Library API has generous but real rate limits. If researching more than 10 competitors:
- Add a 2-second delay between API calls (configurable in the skill)
- Split research across two runs (e.g., competitors 1-5 on Monday, 6-10 on Tuesday)
- Consider upgrading your Meta API access (some research-tier permissions allow higher limits)

### "Ads are missing impression data"

Not all ads have impression range data exposed via the API. This is more common for non-EU advertisers. If impression data is missing:
- Fall back to runtime as the primary signal (60+ day ads are confirmed winners regardless of impression data)
- Note in the report which ads have incomplete data

### "An ad I saw in the library isn't in my results"

Most likely cause: the ad was paused after you saw it but before the API call. The API only returns currently-active ads. The disappeared-ads section will catch this on the next weekly run.

Alternatively, the ad might be running in a country other than the one you specified. Adjust the `ad_reached_countries` parameter.

### "I want to track an ad that's currently in early-test status"

Add it to a watchlist file at `./config/watchlist.json`. The skill will check its status every run and notify you when it moves to a higher confidence tier (or disappears).

```json
{
  "watchlist": [
    {
      "ad_snapshot_url": "https://...",
      "added_date": "2026-08-04",
      "notes": "Looks promising, watch for scaling"
    }
  ]
}
```

---

## Privacy and Ethics

Everything this skill accesses is publicly available through Meta's Ad Library, which Meta operates as a transparency tool. You're not scraping; you're using Meta's official API.

You're analyzing structural patterns (hook types, formats, offer structures, runtime durations) — not copying competitor copy verbatim. Patterns are not protected by copyright. Words are.

When reverse-engineering a competitor advertorial via Pillar 4 (advertorial-builder), the same principle applies. You're using their structural framework (the five-beat DR framework that every advertorial uses), not their words.

---

## Notes

- Run this every Monday morning. The pattern signal is strongest when you have weekly comparison data.
- The first run won't have week-over-week comparisons (no baseline yet). After 4 weeks, the trend data becomes useful.
- For agencies, run this skill once per client niche. Don't combine competitor lists across clients in different verticals — the patterns won't be comparable.
- The Q1 2026 impression-sort feature is mandated by EU DSA, which makes it highly likely to remain available. But if Meta removes the feature, this skill degrades gracefully — runtime longevity alone is still a strong winner signal.
