Help us improve
Share bugs, ideas, or general feedback.
From motion-creative
Weekly competitive intelligence scan — tracks competitor ad strategies, messaging shifts, and creative patterns. Compares against last week's baseline to surface what changed. Use for "competitor scan", "what are competitors doing", "competitive intel", "competitor watch", or "what changed in the market".
npx claudepluginhub motion-creative/motion-creative-plugin --plugin motion-creativeHow this skill is triggered — by the user, by Claude, or both
Slash command
/motion-creative:competitor-watchopusThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
A self-contained weekly competitive scan that any Motion customer can run. Tracks competitor ad strategies, messaging shifts, creative patterns, and new launches — then compares against last week's baseline to surface what actually changed.
Analyze competitor ad libraries — surface creative trends, formats, hooks, and messaging strategies across the industry.
Analyzes competitor ads across Google, Meta, LinkedIn, TikTok, and Microsoft using ad libraries and auction insights. Evaluates copy, creatives, keywords, spend, and identifies gaps/opportunities.
Analyzes competitor ad copy, creative strategy, keyword targeting, and estimated spend across Google, Meta, LinkedIn, TikTok, Microsoft, and Apple Ads. Identifies competitive gaps and opportunities.
Share bugs, ideas, or general feedback.
A self-contained weekly competitive scan that any Motion customer can run. Tracks competitor ad strategies, messaging shifts, creative patterns, and new launches — then compares against last week's baseline to surface what actually changed.
No external context required. This skill uses only the Motion MCP and stores its own baselines. No repo, no strategy docs, no internal knowledge base needed.
Core principle: The value is in the delta, not the state. "Foreplay launched 6 new Lens-focused ads this week" is intelligence. "Foreplay has 41 active ads" is a fact sheet. Every finding answers: "What should I pay attention to this week?"
Baseline model: First run establishes a baseline. Every subsequent run compares current state to the previous week's baseline, reports what changed, and updates the baseline. Baselines are stored locally as markdown files.
--competitor: Optional. A domain (e.g., foreplay.co) to scan a single competitor. If omitted, scan all saved competitors.--baseline-only: Establish baselines without producing a delta report. Use for first run.Call get_auth_context().
If multiple workspaces exist, ask the user which one to scan. Store the workspaceId for all subsequent calls.
Check for a saved watchlist at ~/.claude/competitor-watch/watchlist.md.
If watchlist exists: Read it. It contains brand names, domains, and resolved brandIds from a previous session. Use these directly — no need to ask again.
If no watchlist exists (first run): Ask the user to set up their competitor watchlist:
"This is your first competitor watch. Who are the 3-5 brands you want to track? Give me their names or website domains and I'll set everything up."
Use AskUserQuestion to collect this. Accept brand names, domains, or both.
Then resolve each brand:
get_brand_by_domain(brandUrl) if a domain was providedsearch_brands(query) with the brand nameOnce all brands are resolved, save the watchlist to ~/.claude/competitor-watch/watchlist.md:
---
created: [YYYY-MM-DD]
updated: [YYYY-MM-DD]
workspace_id: [workspaceId]
---
# Competitor Watchlist
| Brand | Domain | Brand ID | Added |
|-------|--------|----------|-------|
| [Name] | [domain] | [brandId] | [YYYY-MM-DD] |
| [Name] | [domain] | [brandId] | [YYYY-MM-DD] |
Updating the watchlist: If the user says "add [brand]" or "remove [brand]" or "change my competitors", update the watchlist file accordingly. The watchlist is the persistent config — it survives across sessions.
get_workspace_brand(workspaceId)
Used for comparison framing — "how does this compare to our own ad strategy?"
Look for baseline files at ~/.claude/competitor-watch/{competitor-slug}.md for each brand on the watchlist. If no baseline exists for a brand, this is a first run for that brand — establish the baseline, don't compute deltas.
For each competitor, dispatch in parallel:
CRITICAL: Always set limit=500 on every get_inspo_creatives call. The API defaults to ~20-50 results if you omit the limit or set it low. Setting limit=500 ensures you get the full portfolio in one call for most brands. This is non-negotiable — partial data produces wrong analysis.
MANDATORY: Two-pass pull for every brand. Even with limit=500, always pull NEWEST and OLDEST and merge. This catches edge cases where the API caps results.
For each competitor, run these queries in parallel:
Query 1a: Active Portfolio — NEWEST first
get_inspo_creatives(brandId, workspaceId, sort="NEWEST", status="ACTIVE", limit=500)
Query 1b: Active Portfolio — OLDEST first (same call, different sort)
get_inspo_creatives(brandId, workspaceId, sort="OLDEST", status="ACTIVE", limit=500)
Query 2: Recently Killed
get_inspo_creatives(brandId, workspaceId, sort="NEWEST", status="INACTIVE", limit=500)
Filter client-side to only those with pauseDate within the last 7 days.
Query 3: Brand Context
get_inspo_brand_context(brandId, workspaceId)
After pulling, merge and deduplicate Query 1a + 1b by creative _id. The merged set is the full active portfolio. Log the count.
Validation gate: Before proceeding to analysis, verify the ad count matches expectations. If a brand shows activeAdCount in its metadata (from workspace competitors or search_brands), compare your pulled count against it. If your count is significantly lower, you missed ads — paginate further or increase the limit.
NEVER set limit below 500. NEVER omit the limit parameter (it defaults too low). NEVER skip the OLDEST pass.
Analyze the complete active portfolio as a body of work — this reveals the competitor's live-in-market strategy:
Format & Production:
Messaging Themes:
Feature & Product Emphasis:
Landing Page Strategy:
Cohort every ad by age and compute survival:
Long-runners (60+ days, still ACTIVE) These are evergreen winners. They've survived multiple creative refresh cycles. Pay attention to what makes them durable.
Survivors (launched 15-60 days ago, still ACTIVE) Proven creative. If it's been running 2+ weeks, they've seen enough data to know it works. This is the strongest signal of what's actually performing.
Testing Zone (launched 7-14 days ago, still ACTIVE) Past the first cut but could still be in evaluation. Moderate signal.
Fresh Tests (launched < 7 days ago) Newest bets. Reveal strategic intent — what they're thinking about right now.
Important: "Inactive" does not mean "failed." An ad can stop running because:
Always reason over the likely reason. Look at content clues (mentions a date/event/sale?), runtime (2+ weeks before killing = probably adequate), and siblings (newer ad with similar messaging = iteration replacement). Quick kills (< 5 days, no promo content) are more likely genuine underperformance.
You can't pull summaries and transcripts for every ad. Use this priority:
Always deep-dive (transcript + full analysis) — 5-8 per competitor:
Summary only (read copy + metadata):
Metadata only (format, CTA, landing page, launch date):
For deep-dives, dispatch Agent sub-agents in parallel:
For each ad: pull get_creative_transcript, extract opening hook (verbatim),
core claim, proof structure, emotional register, CTA, competitive positioning,
feature depth. Return a structured brief card.
Group ads into clusters that reveal the creative strategy:
For the full portfolio, answer: If a prospect evaluating your brand saw these ads, how would it make them think about you?
Run the same analysis on your own brand's ads. This creates the comparison frame.
Use the brandId from get_workspace_brand. Pull the EXACT same way as competitors — limit=500, two-pass NEWEST+OLDEST, merge and deduplicate:
get_inspo_creatives(brandId, workspaceId, sort="NEWEST", status="ACTIVE", limit=500)
get_inspo_creatives(brandId, workspaceId, sort="OLDEST", status="ACTIVE", limit=500)
get_inspo_creatives(brandId, workspaceId, sort="NEWEST", status="INACTIVE", limit=500)
Merge active pulls by _id. Filter inactive to pauseDate within last 7 days. Do NOT use a lower limit for your own brand than competitors.
Apply the same framework: format distribution, messaging themes, survival analysis, test clusters.
For every competitor finding, provide the own-brand comparison:
Don't just compare numbers — interpret what the gap means. A format gap might be intentional or a blind spot worth testing.
If a baseline exists from the previous scan, compute what changed:
Volume & Velocity:
Strategic Shifts:
What They Stopped Doing:
What Survived:
Signal Strength:
| Signal | Strength | Why |
|---|---|---|
| A survivor from 15+ days with a new messaging angle | Very High | Proven message they're scaling |
| 3+ fresh tests all exploring the same new theme | High | Coordinated strategic bet |
| A feature promotion for something you don't have | High | Competitive gap |
| Format mix shift (e.g., UGC ratio doubled) | Medium | Production strategy change |
| Volume spike or drop vs last week | Medium | Resource allocation signal |
| Single ad with an unusual approach | Low-Medium | Could be a one-off test |
| Minor copy variations on existing themes | Low | Skip unless pattern emerges |
# Competitor Watch — [Date]
**Workspace:** [name] | **Competitors:** [N scanned] | **Baseline:** [first run / delta from YYYY-MM-DD]
---
## What Changed This Week
[3-5 bullets MAX. Only findings that matter. Each: what shifted + why it matters + what to consider.
If nothing significant: "Stable week — no major competitive shifts detected."]
---
## Competitor Intel
### [Competitor Name] — [one-line: quiet / active / shifting / launching]
**Active Portfolio:** [N] total | Video [X%] / Static [Y%]
**30-Day Launches:** [N] launched | [N] survived | [N] killed | [X%] survival rate
**Weekly Cadence:** [accelerating / steady / slowing / paused]
**Live Strategy:**
- [Top messaging themes, ranked by frequency]
- [Dominant hooks and emotional registers — quote the actual hooks]
- [Format & production strategy]
- [Features being promoted]
**Survivors (15+ days, still running):**
- [What they have in common — the pattern that's working]
**Fresh Tests (this week):**
- [New launches — what they're testing, what it signals]
**Test Clusters:**
- [Cluster 1: name the bet, N ads, what they're varying]
**Competitive Eval:**
- [If a prospect saw these ads, how would it affect your deals?]
**Delta from Last Week:**
- [What's new, what's gone, what shifted. Skip if first run.]
[Repeat per competitor. Skip sections with no content.]
---
## Your Brand Benchmark
**Your Active Portfolio:** [N] total | Video [X%] / Static [Y%]
**30-Day Survival Rate:** [X%]
**How You Compare:**
| Dimension | You | [Comp 1] | [Comp 2] | [Comp 3] | Read |
|-----------|-----|----------|----------|----------|------|
| Active ads | [N] | [N] | [N] | [N] | [who's investing more?] |
| Oldest active ad | [days] | [days] | [days] | [days] | [portfolio maturity] |
| Video/static mix | [%] | [%] | [%] | [%] | [format strategy] |
| Visual format diversity | [N types] | [N] | [N] | [N] | [creative range] |
| Customer proof in ads | [Y/N] | [Y/N] | [Y/N] | [Y/N] | [credibility gap?] |
| Biggest bet | [what] | [what] | [what] | [what] | [strategic direction] |
| Key feature promoted | [what] | [what] | [what] | [what] | [positioning overlap] |
| Comment-gate CTAs | [Y/N] | [Y/N] | [Y/N] | [Y/N] | [engagement tactic] |
**Gaps worth testing:**
- [Things competitors do that you don't — worth a test?]
- [Things you do that nobody else does — double down?]
---
## Recommended Actions
[2-3 specific, grounded-in-findings recommendations.
Each connects to a specific finding above.
Not "diversify your creative mix" — instead: "Test a UGC creator ad using
the solopreneur burnout angle that's been running 27 days for [competitor]."]
After producing the report, write the new baseline for each scanned competitor.
Write to ~/.claude/competitor-watch/{competitor-slug}.md:
---
competitor: [Name]
brand_id: [brandId]
last_scanned: [YYYY-MM-DD]
---
# [Competitor Name] — Weekly Baseline
## Portfolio Snapshot
**Active Ad Count:** [N]
**Format Mix:** [video X% / static Y%]
**Production Styles:** [UGC, screen recording, etc.]
## Active Ad Inventory
[For each active ad: ID, format, hook (verbatim), CTA, landing page, launch date, days active]
## Messaging Themes
- [theme 1 — frequency, example hook]
- [theme 2 — frequency, example hook]
## Survival Cohorts
**60+ day long-runners:** [list with IDs]
**15-60 day survivors:** [list with IDs]
**7-14 day zone:** [list]
**< 7 day fresh tests:** [list]
## Test Clusters
- [Cluster name: ad IDs, what they're varying]
## Features Promoted
- [ranked list]
## Brand Context Summary
[positioning, voice, audience from get_inspo_brand_context if available]
~/.claude/competitor-watch/ — outside any repo, purely local--competitor flag: Trigger first-run onboarding — ask for 3-5 brands to trackAfter producing the report and updating baselines, deliver it to the team and prompt for recurring scheduling.
Create a Slack canvas containing the full competitor watch report using slack_create_canvas:
Competitor Watch — [YYYY-MM-DD]Craft a short, high-signal Slack message that makes people want to open the canvas. This is NOT a summary — it's a teaser.
Structure:
🔍 *Competitor Watch — [Date]*
[One punchy headline: the single most surprising or actionable finding. Make it specific and provocative enough that someone stops scrolling.]
*Top signals this week:*
• [Insight 1 — the sharpest competitive move. Quote a specific hook or claim. Name the competitor.]
• [Insight 2 — something that directly affects your team's next creative decisions]
Full report → [canvas will auto-attach]
Rules for the message:
slack_channel_id). If not configured, ask which channel to post to.slack_create_canvasslack_send_message. Ask the user for permission before sending.After the first successful run, ask the user if they want this automated:
"Want me to run this every Monday morning and post to [channel]? I'll scan all competitors, generate the report, and drop the highlights in Slack automatically."
If yes, create a scheduled task:
competitor-watch-weekly0 9 * * 1 — 9am local)Only prompt for scheduling on the first run or if no competitor-watch-weekly task exists. On subsequent runs, just deliver silently.
After the scan:
/industry-trends --brand [domain]/create-concepts with competitive context/performance-analysis/build-brief