Skip to content
Marketing
Skill

/competitor-pr-finder

Give it your product URL or description. It finds your top 5 competitors, runs three-track PR research across all of them (editorial, podcasts, communities), identifies which channels appear most frequently, looks up the journalist or host for each, and returns a tiered outreach

From plugin
opendirectory-gtm-skills
70765 skills

Claude Code

$ npx -y skills add Varnan-Tech/opendirectory --skill competitor-pr-finder --agent claude-code

SKILL.md

competitor-pr-finder.SKILL.md
name: competitor-pr-finder
description: 'Give it your product URL or description. It finds your top 5 competitors, runs three-track PR research across all of them (editorial, podcasts, communities), identifies which channels appear most frequently, looks up the journalist or host for each, and returns a tiered outreach list with story angles and ready-to-send cold pitch drafts tailored to your product. Use when asked to find PR opportunities, discover where competitors got featured, build a media outreach list, find which journalists cover my space, or get pitch templates for press coverage.'

Competitor PR Finder

Give it your product URL. It finds your competitors, researches every PR channel they used (news, podcasts, communities), surfaces the channels that appear across multiple competitors (your proven targets), finds the journalist or host for each, and drafts a personalized cold pitch for your product at every tier-1 channel.

---

**Zero-hallucination policy:** Every channel, journalist name, story angle, and pitch detail in the output must trace to a specific Tavily search result or the fetched product page. This applies to:

  • Competitor names: must appear in Tavily search results, not AI training knowledge
  • Channel names: must have a URL in the search results
  • Journalist/host names: must appear verbatim in a Tavily snippet
  • Story angles: extracted from article/episode titles in search results only
  • Pitch drafts: reference specific evidence from search data + product analysis

---

Common Mistakes

| The agent will want to... | Why that's wrong | |---|---| | Name a journalist from training knowledge | Every journalist name must trace to a search result snippet. Writing "Sarah Perez covers startups at TechCrunch" from memory is hallucination. | | List channels without evidence URLs | Every channel in the output must have at least one URL from the PR search results proving a competitor was featured there. | | Skip the competitor confirmation step | Always show discovered competitors and wait for the user to confirm. Wrong competitors = wasted searches and a useless output. | | Generate generic pitches ("We'd love to be featured") | Every pitch must reference a specific angle from the evidence AND a specific differentiator from the product analysis. | | Mark a channel as Tier 1 with only 1 competitor occurrence | Tier 1 = 3+ competitors. Tier 2 = exactly 2. Tier 3 = 1. Do not promote channels that haven't proven themselves. | | Use em dashes in output | Replace all em dashes (--) with hyphens. |

---

Read Reference Files Before Each Run

cat references/pr-channel-types.md
cat references/pitch-guide.md
cat references/tier-scoring.md

---

Step 1: Setup Check

echo "TAVILY_API_KEY:    ${TAVILY_API_KEY:+set}${TAVILY_API_KEY:-NOT SET -- required}"
echo "FIRECRAWL_API_KEY: ${FIRECRAWL_API_KEY:+set}${FIRECRAWL_API_KEY:-not set, Tavily extract will be used as fallback}"

**If TAVILY_API_KEY is missing:** Stop immediately. Tell the user: "TAVILY_API_KEY is required to research competitors and find PR coverage. There is no fallback. Get it at app.tavily.com -- free tier: 1000 credits/month (about 43 full runs at ~23 searches/run). Add it to your .env file."

**If only FIRECRAWL_API_KEY is missing:** Continue. Tavily extract will be used for the URL fetch.

---

Step 2: Parse Input

Collect from the conversation:

  • `product_url`: the URL to fetch (required, unless user pastes a description directly)
  • `product_name`: optional, derived from page if not provided
  • `geography`: optional -- US / Europe / global. Default: US

**If the user provides only a pasted description (no URL):** Skip Steps 3 and 4. Go directly to Step 4 (product analysis) using the pasted text as `product_content`. Set `page_source` to `user_description` and note in `data_quality_flags`.

**If neither URL nor description:** Ask: "What is the URL of your product or startup? Or paste a short description: what it does, who it is for, and what makes it different from competitors."

Derive product slug:

PRODUCT_SLUG=$(python3 -c "
from urllib.parse import urlparse
import sys
url = 'URL_HERE'
if url.startswith('http'):
    host = urlparse(url).netloc.replace('www.', '')
    print(host.split('.')[0])
else:
    import re
    print(re.sub(r'[^a-z0-9]', '-', url[:30].lower()).strip('-'))
")
echo "Product slug: $PRODUCT_SLUG"

---

Step 3: Fetch Product Page

**Primary: Firecrawl (if FIRECRAWL_API_KEY is set)**

curl -s -X POST https://api.firecrawl.dev/v1/scrape \
  -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "URL_HERE", "formats": ["markdown"], "onlyMainContent": true}' \
  | python3 -c "
import sys, json
d = json.load(sys.stdin)
content = d.get('data', {}).get('markdown', '') or d.get('markdown', '')
print(f'Fetched via Firecrawl: {len(content)} characters')
open('/tmp/cprf-product-raw.md', 'w').write(content)
"

**Fallback: Tavily extract (if FIRECRAWL_API_KEY is not set)**

curl -s -X POST https://api.tavily.com/extract \
  -H "Content-Type: application/json" \
  -d "{\"api_key\": \"$TAVILY_API_KEY\", \"urls\": [\"URL_HERE\"]}" \
  | python3 -c "
import sys, json
d = json.load(sys.stdin)
content = d.get('results', [{}])[0].get('raw_content', '')
print(f'Fetched via Tavily extract: {len(content)} characters')
open('/tmp/cprf-product-raw.md', 'w').write(content)
"

**Checkpoint:**

python3 -c "
content = open('/tmp/cprf-product-raw.md').read()
if len(content) < 200:
    print('ERROR: fewer than 200 characters fetched')
else:
    print(f'Content OK: {len(content)} characters')
"

**If content < 200 characters:** Stop fetching. Tell the user: "The product page returned no readable content -- the site is likely JavaScript-rendered and blocked the fetch. Please paste a short description directly: what it does, who it is for, and what makes it different."

---

Step 4: Prod

Read more
@varnan-tech
Ships withopendirectory-gtm-skills

AI Agent Skills built for Founders who hate Marketing

Stars on GitHub

Momentum

stars in total
707
Star history of Varnan-Tech/opendirectory on GitHub, a chart by star-history.com

Other skills on opendirectory-gtm-skills.

More skills from other plugins.

seo

seo

Comprehensive SEO analysis for any website or business type. Full site audits, single-page analysis, technical SEO (crawlability,…

@agricidaniel@agricidanielInstall Skill
brag

brag

Turn the current project website into a short, polished, shareable launch video using Hyperframes. Use when someone says "/brag",…

brag3w21k
@latent-spaces@latent-spacesInstall Skill
geo-audit

geo-audit

Full website GEO+SEO audit with parallel subagent delegation. Orchestrates a comprehensive Generative Engine Optimization audit…

Questions about competitor-pr-finder.

Which coding agents can use competitor-pr-finder?
competitor-pr-finder installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.