competitive-monitoring
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCompetitive Monitoring
竞品监控
Track competitor websites for changes in pricing, features, positioning, and content.
跟踪竞品网站的价格、功能、定位及内容变化。
Quick Start
快速开始
bash
undefinedbash
undefinedCapture initial snapshot
捕获初始快照
/ork:competitive-monitoring capture https://competitor.com/pricing
/ork:competitive-monitoring capture https://competitor.com/pricing
Check for changes (compares to last snapshot)
检查变化(与上一次快照对比)
/ork:competitive-monitoring diff https://competitor.com/pricing
/ork:competitive-monitoring diff https://competitor.com/pricing
View change history
查看变更历史
/ork:competitive-monitoring history competitor.com
undefined/ork:competitive-monitoring history competitor.com
undefinedCore Concepts
核心概念
Snapshot
Snapshot
A point-in-time capture of a webpage including:
- Text content - Main body text
- Structured data - Pricing tiers, feature lists, etc.
- Screenshot - Visual state
- Metadata - Timestamp, URL, capture method
某一时刻的网页捕获内容,包括:
- 文本内容 - 页面主体文本
- 结构化数据 - 定价套餐、功能列表等
- 截图 - 页面视觉状态
- 元数据 - 时间戳、URL、捕获方法
Diff
Diff
Comparison between two snapshots showing:
- Added content - New text, features, prices
- Removed content - Deleted sections
- Changed content - Modified values
- Visual changes - Layout/design shifts
对比两个快照,展示:
- 新增内容 - 新文本、功能、价格
- 移除内容 - 删除的板块
- 修改内容 - 变更的值
- 视觉变化 - 布局/设计调整
Change Classification
变更分类
| Severity | Examples | Action |
|---|---|---|
| Critical | Price increase/decrease, major feature change | Immediate alert |
| High | New feature added, feature removed | Review required |
| Medium | Copy changes, positioning shift | Note for analysis |
| Low | Typos, minor styling | Log only |
| 严重程度 | 示例 | 操作 |
|---|---|---|
| 严重 | 价格上涨/下调、重大功能变更 | 立即告警 |
| 高 | 新增功能、移除功能 | 需要审核 |
| 中 | 文案修改、定位调整 | 记录用于分析 |
| 低 | 拼写错误、样式微调 | 仅记录 |
Site Discovery with Tavily (Optional Pre-Step)
借助Tavily发现站点(可选前置步骤)
When is available, use Tavily's crawl API to discover and extract all key pages on a competitor's site in one call. This replaces the manual map→extract two-step workflow.
TAVILY_API_KEY当配置后,可使用Tavily的爬取API一键发现并提取竞品站点的所有关键页面,替代手动的映射→提取两步流程。
TAVILY_API_KEYOption A: Crawl (Recommended — Single Call)
选项A:爬取(推荐——一键操作)
bash
undefinedbash
undefinedCrawl competitor site — discovers URLs and extracts content in one step
爬取竞品站点——一步完成URL发现与内容提取
curl -s -X POST 'https://api.tavily.com/crawl'
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d '{ "url": "https://competitor.com", "max_depth": 2, "limit": 50, "include_raw_content": "markdown", "include_paths": ["/pricing*", "/features*", "/changelog*", "/blog*"] }' | python3 -c " import json, sys data = json.load(sys.stdin) for page in data.get('results', []): fname = page['url'].replace('https://', '').replace('/', '_') with open(f'.competitive-intel/snapshots/{fname}.md', 'w') as f: f.write(page.get('raw_content', page.get('content', ''))) print(f'Captured: {page["url"]}') "
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d '{ "url": "https://competitor.com", "max_depth": 2, "limit": 50, "include_raw_content": "markdown", "include_paths": ["/pricing*", "/features*", "/changelog*", "/blog*"] }' | python3 -c " import json, sys data = json.load(sys.stdin) for page in data.get('results', []): fname = page['url'].replace('https://', '').replace('/', '_') with open(f'.competitive-intel/snapshots/{fname}.md', 'w') as f: f.write(page.get('raw_content', page.get('content', ''))) print(f'Captured: {page["url"]}') "
undefinedcurl -s -X POST 'https://api.tavily.com/crawl'
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d '{ "url": "https://competitor.com", "max_depth": 2, "limit": 50, "include_raw_content": "markdown", "include_paths": ["/pricing*", "/features*", "/changelog*", "/blog*"] }' | python3 -c " import json, sys data = json.load(sys.stdin) for page in data.get('results', []): fname = page['url'].replace('https://', '').replace('/', '_') with open(f'.competitive-intel/snapshots/{fname}.md', 'w') as f: f.write(page.get('raw_content', page.get('content', ''))) print(f'Captured: {page["url"]}') "
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d '{ "url": "https://competitor.com", "max_depth": 2, "limit": 50, "include_raw_content": "markdown", "include_paths": ["/pricing*", "/features*", "/changelog*", "/blog*"] }' | python3 -c " import json, sys data = json.load(sys.stdin) for page in data.get('results', []): fname = page['url'].replace('https://', '').replace('/', '_') with open(f'.competitive-intel/snapshots/{fname}.md', 'w') as f: f.write(page.get('raw_content', page.get('content', ''))) print(f'Captured: {page["url"]}') "
undefinedOption B: Map + Extract (Granular Control)
选项B:映射+提取(精细控制)
Use when you need to filter URLs before extracting:
bash
undefined当需要在提取前过滤URL时使用此方式:
bash
undefinedStep 1: Discover URLs
步骤1:发现URL
curl -s -X POST 'https://api.tavily.com/map'
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d '{"url": "https://competitor.com", "max_depth": 2, "limit": 50}'
| python3 -c " import json, sys for url in json.load(sys.stdin).get('urls', []): print(url) " > .competitive-intel/discovered-urls.txt
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d '{"url": "https://competitor.com", "max_depth": 2, "limit": 50}'
| python3 -c " import json, sys for url in json.load(sys.stdin).get('urls', []): print(url) " > .competitive-intel/discovered-urls.txt
curl -s -X POST 'https://api.tavily.com/map'
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d '{"url": "https://competitor.com", "max_depth": 2, "limit": 50}'
| python3 -c " import json, sys for url in json.load(sys.stdin).get('urls', []): print(url) " > .competitive-intel/discovered-urls.txt
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d '{"url": "https://competitor.com", "max_depth": 2, "limit": 50}'
| python3 -c " import json, sys for url in json.load(sys.stdin).get('urls', []): print(url) " > .competitive-intel/discovered-urls.txt
Step 2: Filter and batch extract
步骤2:过滤并批量提取
URLS=$(grep -E '(pricing|features|changelog)' .competitive-intel/discovered-urls.txt
| head -20 | python3 -c "import json,sys; print(json.dumps([l.strip() for l in sys.stdin if l.strip()]))")
| head -20 | python3 -c "import json,sys; print(json.dumps([l.strip() for l in sys.stdin if l.strip()]))")
curl -s -X POST 'https://api.tavily.com/extract'
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d "{"urls": $URLS}" | python3 -m json.tool
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d "{"urls": $URLS}" | python3 -m json.tool
**Cost**: Crawl ~1 credit/5 pages. Map+Extract ~1 credit/10 mapped + 1 credit/5 extracted. Skip if `TAVILY_API_KEY` unset — proceed directly to browser-based capture below.URLS=$(grep -E '(pricing|features|changelog)' .competitive-intel/discovered-urls.txt
| head -20 | python3 -c "import json,sys; print(json.dumps([l.strip() for l in sys.stdin if l.strip()]))")
| head -20 | python3 -c "import json,sys; print(json.dumps([l.strip() for l in sys.stdin if l.strip()]))")
curl -s -X POST 'https://api.tavily.com/extract'
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d "{"urls": $URLS}" | python3 -m json.tool
-H 'Content-Type: application/json'
-H "Authorization: Bearer $TAVILY_API_KEY"
-d "{"urls": $URLS}" | python3 -m json.tool
**成本**:爬取约1积分/5页。映射+提取约1积分/10个映射页面 + 1积分/5个提取页面。若未设置`TAVILY_API_KEY`则跳过此步骤,直接使用下方基于浏览器的捕获方式。Workflow
工作流
Step 1: Initial Capture
步骤1:初始捕获
bash
undefinedbash
undefinedCreate snapshots directory
创建快照目录
mkdir -p .competitive-intel/snapshots
mkdir -p .competitive-intel/snapshots
Capture competitor pricing page
捕获竞品定价页面
agent-browser open https://competitor.com/pricing
agent-browser wait --load networkidle
agent-browser open https://competitor.com/pricing
agent-browser wait --load networkidle
Save text content
保存文本内容
agent-browser get text body > .competitive-intel/snapshots/competitor-pricing-$(date +%Y%m%d).txt
agent-browser get text body > .competitive-intel/snapshots/competitor-pricing-$(date +%Y%m%d).txt
Save screenshot
保存截图
agent-browser screenshot .competitive-intel/snapshots/competitor-pricing-$(date +%Y%m%d).png
agent-browser screenshot .competitive-intel/snapshots/competitor-pricing-$(date +%Y%m%d).png
Extract structured pricing data
提取结构化定价数据
agent-browser eval "JSON.stringify(
Array.from(document.querySelectorAll('.pricing-tier')).map(tier => ({
name: tier.querySelector('h3')?.innerText,
price: tier.querySelector('.price')?.innerText,
features: Array.from(tier.querySelectorAll('li')).map(li => li.innerText)
}))
)" > .competitive-intel/snapshots/competitor-pricing-$(date +%Y%m%d).json
agent-browser close
undefinedagent-browser eval "JSON.stringify(
Array.from(document.querySelectorAll('.pricing-tier')).map(tier => ({
name: tier.querySelector('h3')?.innerText,
price: tier.querySelector('.price')?.innerText,
features: Array.from(tier.querySelectorAll('li')).map(li => li.innerText)
}))
)" > .competitive-intel/snapshots/competitor-pricing-$(date +%Y%m%d).json
agent-browser close
undefinedStep 2: Diff Detection
步骤2:差异检测
bash
undefinedbash
undefinedGet latest two snapshots
获取最新两个快照
LATEST=$(ls -t .competitive-intel/snapshots/competitor-pricing-.txt | head -1)
PREVIOUS=$(ls -t .competitive-intel/snapshots/competitor-pricing-.txt | head -2 | tail -1)
LATEST=$(ls -t .competitive-intel/snapshots/competitor-pricing-.txt | head -1)
PREVIOUS=$(ls -t .competitive-intel/snapshots/competitor-pricing-.txt | head -2 | tail -1)
Text diff
文本差异对比
diff -u "$PREVIOUS" "$LATEST" > .competitive-intel/diffs/competitor-pricing-$(date +%Y%m%d).diff
diff -u "$PREVIOUS" "$LATEST" > .competitive-intel/diffs/competitor-pricing-$(date +%Y%m%d).diff
Check if significant changes
检查是否有重大变化
if [ -s ".competitive-intel/diffs/competitor-pricing-$(date +%Y%m%d).diff" ]; then
echo "Changes detected!"
cat ".competitive-intel/diffs/competitor-pricing-$(date +%Y%m%d).diff"
fi
undefinedif [ -s ".competitive-intel/diffs/competitor-pricing-$(date +%Y%m%d).diff" ]; then
echo "Changes detected!"
cat ".competitive-intel/diffs/competitor-pricing-$(date +%Y%m%d).diff"
fi
undefinedStep 3: Structured Comparison
步骤3:结构化对比
bash
undefinedbash
undefinedCompare JSON pricing data
对比JSON格式的定价数据
LATEST_JSON=$(ls -t .competitive-intel/snapshots/competitor-pricing-.json | head -1)
PREVIOUS_JSON=$(ls -t .competitive-intel/snapshots/competitor-pricing-.json | head -2 | tail -1)
LATEST_JSON=$(ls -t .competitive-intel/snapshots/competitor-pricing-.json | head -1)
PREVIOUS_JSON=$(ls -t .competitive-intel/snapshots/competitor-pricing-.json | head -2 | tail -1)
Use jq to compare
使用jq工具对比
jq -s '
.[0] as $old | .[1] as $new |
{
price_changes: [
$new[] | . as $tier |
($old[] | select(.name == $tier.name)) as $old_tier |
select($old_tier.price != $tier.price) |
{name: .name, old_price: $old_tier.price, new_price: .price}
],
new_tiers: [$new[] | select(.name as $n | $old | map(.name) | index($n) | not)],
removed_tiers: [$old[] | select(.name as $n | $new | map(.name) | index($n) | not)]
}
' "$PREVIOUS_JSON" "$LATEST_JSON"
undefinedjq -s '
.[0] as $old | .[1] as $new |
{
price_changes: [
$new[] | . as $tier |
($old[] | select(.name == $tier.name)) as $old_tier |
select($old_tier.price != $tier.price) |
{name: .name, old_price: $old_tier.price, new_price: .price}
],
new_tiers: [$new[] | select(.name as $n | $old | map(.name) | index($n) | not)],
removed_tiers: [$old[] | select(.name as $n | $new | map(.name) | index($n) | not)]
}
' "$PREVIOUS_JSON" "$LATEST_JSON"
undefinedMonitoring Targets
监控目标
Pricing Pages
定价页面
bash
undefinedbash
undefinedExtract pricing structure
提取定价结构
agent-browser eval "JSON.stringify({
tiers: Array.from(document.querySelectorAll('[class*=pricing], [class*=plan]')).map(t => ({
name: t.querySelector('h2, h3, [class*=title]')?.innerText?.trim(),
price: t.querySelector('[class*=price], [class*=cost]')?.innerText?.trim(),
period: t.querySelector('[class*=period], [class*=billing]')?.innerText?.trim(),
cta: t.querySelector('button, [class*=cta]')?.innerText?.trim()
}))
})"
undefinedagent-browser eval "JSON.stringify({
tiers: Array.from(document.querySelectorAll('[class*=pricing], [class*=plan]')).map(t => ({
name: t.querySelector('h2, h3, [class*=title]')?.innerText?.trim(),
price: t.querySelector('[class*=price], [class*=cost]')?.innerText?.trim(),
period: t.querySelector('[class*=period], [class*=billing]')?.innerText?.trim(),
cta: t.querySelector('button, [class*=cta]')?.innerText?.trim()
}))
})"
undefinedFeature Pages
功能页面
bash
undefinedbash
undefinedExtract feature list
提取功能列表
agent-browser eval "JSON.stringify({
features: Array.from(document.querySelectorAll('[class*=feature] h3, [class*=feature] h4')).map(f => f.innerText?.trim()),
categories: Array.from(document.querySelectorAll('[class*=category]')).map(c => ({
name: c.querySelector('h2, h3')?.innerText?.trim(),
items: Array.from(c.querySelectorAll('li')).map(li => li.innerText?.trim())
}))
})"
undefinedagent-browser eval "JSON.stringify({
features: Array.from(document.querySelectorAll('[class*=feature] h3, [class*=feature] h4')).map(f => f.innerText?.trim()),
categories: Array.from(document.querySelectorAll('[class*=category]')).map(c => ({
name: c.querySelector('h2, h3')?.innerText?.trim(),
items: Array.from(c.querySelectorAll('li')).map(li => li.innerText?.trim())
}))
})"
undefinedChangelog/Release Notes
更新日志/版本说明
bash
undefinedbash
undefinedExtract recent releases
提取近期版本
agent-browser eval "JSON.stringify({
releases: Array.from(document.querySelectorAll('[class*=release], [class*=changelog] > div')).slice(0, 10).map(r => ({
version: r.querySelector('[class*=version], h2, h3')?.innerText?.trim(),
date: r.querySelector('[class*=date], time')?.innerText?.trim(),
notes: r.querySelector('[class*=notes], [class*=description]')?.innerText?.trim()?.slice(0, 200)
}))
})"
undefinedagent-browser eval "JSON.stringify({
releases: Array.from(document.querySelectorAll('[class*=release], [class*=changelog] > div')).slice(0, 10).map(r => ({
version: r.querySelector('[class*=version], h2, h3')?.innerText?.trim(),
date: r.querySelector('[class*=date], time')?.innerText?.trim(),
notes: r.querySelector('[class*=notes], [class*=description]')?.innerText?.trim()?.slice(0, 200)
}))
})"
undefinedStorage Pattern
存储模式
.competitive-intel/
├── config.json # Monitored URLs and schedules
├── snapshots/
│ ├── competitor-a/
│ │ ├── pricing-0201.txt
│ │ ├── pricing-0201.json
│ │ └── pricing-0201.png
│ └── competitor-b/
│ └── ...
├── diffs/
│ ├── competitor-a/
│ │ └── pricing-0201.diff
│ └── competitor-b/
│ └── ...
└── reports/
└── weekly-0201.md.competitive-intel/
├── config.json # 监控的URL及调度配置
├── snapshots/
│ ├── competitor-a/
│ │ ├── pricing-0201.txt
│ │ ├── pricing-0201.json
│ │ └── pricing-0201.png
│ └── competitor-b/
│ └── ...
├── diffs/
│ ├── competitor-a/
│ │ └── pricing-0201.diff
│ └── competitor-b/
│ └── ...
└── reports/
└── weekly-0201.mdConfig File
配置文件
json
{
"monitors": [
{
"name": "Competitor A Pricing",
"url": "https://competitor-a.com/pricing",
"frequency": "daily",
"selectors": {
"pricing": ".pricing-tier",
"features": ".feature-list li"
},
"alerts": {
"price_change": "critical",
"new_feature": "high",
"copy_change": "low"
}
}
],
"storage": ".competitive-intel",
"retention_days": 90
}json
{
"monitors": [
{
"name": "Competitor A Pricing",
"url": "https://competitor-a.com/pricing",
"frequency": "daily",
"selectors": {
"pricing": ".pricing-tier",
"features": ".feature-list li"
},
"alerts": {
"price_change": "critical",
"new_feature": "high",
"copy_change": "low"
}
}
],
"storage": ".competitive-intel",
"retention_days": 90
}Change Report Template
变更报告模板
markdown
undefinedmarkdown
undefinedCompetitive Change Report
竞品变更报告
Date: 2026-02-04
Competitor: Competitor A
URL: https://competitor-a.com/pricing
日期: 2026-02-04
竞品: Competitor A
URL: https://competitor-a.com/pricing
Summary
摘要
- Critical Changes: 1 (price increase)
- High Changes: 2 (new features)
- Medium Changes: 0
- Low Changes: 3 (copy updates)
- 严重变更: 1项(价格上涨)
- 高优先级变更: 2项(新增功能)
- 中优先级变更: 0项
- 低优先级变更: 3项(文案更新)
Critical: Price Change Detected
严重:检测到价格变更
| Tier | Previous | Current | Change |
|---|---|---|---|
| Pro | $29/mo | $39/mo | +34% |
| 套餐 | 原价格 | 当前价格 | 变化幅度 |
|---|---|---|---|
| Pro | $29/月 | $39/月 | +34% |
High: New Features Added
高优先级:新增功能
- AI Assistant - Added to Pro tier
- API Access - Now available in Team tier
- AI Assistant - 新增至Pro套餐
- API Access - 现面向Team套餐开放
Recommendation
建议
- Update competitive positioning
- Review our pricing strategy
- Consider matching new AI feature
undefined- 更新竞品定位分析
- 审核我方定价策略
- 考虑匹配新增AI功能
undefinedIntegration with Memory
与记忆模块集成
Store findings in knowledge graph for persistence:
bash
undefined将发现的信息存储到知识图谱中以持久化:
bash
undefinedAfter detecting changes, store in memory
检测到变更后,存储到记忆模块
mcp__memory__add_node(
name="Competitor A Price Increase -02",
type="competitive_intelligence",
content="Pro tier increased from $29 to $39 (+34%)"
)
mcp__memory__add_node(
name="Competitor A Price Increase -02",
type="competitive_intelligence",
content="Pro tier increased from $29 to $39 (+34%)"
)
Query historical changes
查询历史变更
mcp__memory__search_nodes(query="competitor pricing changes ")
undefinedmcp__memory__search_nodes(query="competitor pricing changes ")
undefinedAutomation Ideas
自动化思路
Scheduled Monitoring (via cron/CI)
定时监控(通过cron/CI)
yaml
undefinedyaml
undefined.github/workflows/competitive-monitor.yml
.github/workflows/competitive-monitor.yml
name: Competitive Monitor
on:
schedule:
- cron: '0 9 * * *' # Daily at 9 AM
jobs:
monitor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g agent-browser
- run: agent-browser install
- run: ./scripts/run-competitive-monitor.sh
- uses: actions/upload-artifact@v4
with:
name: competitive-intel
path: .competitive-intel/
undefinedname: Competitive Monitor
on:
schedule:
- cron: '0 9 * * *' # 每日上午9点
jobs:
monitor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g agent-browser
- run: agent-browser install
- run: ./scripts/run-competitive-monitor.sh
- uses: actions/upload-artifact@v4
with:
name: competitive-intel
path: .competitive-intel/
undefinedRelated Skills
相关技能
- - Decides WebFetch vs browser
web-research-workflow - - Detailed capture patterns
browser-content-capture - - Analysis frameworks
market-analysis-patterns
Version: 1.1.0 (February 2026)
- - 决定使用WebFetch还是浏览器
web-research-workflow - - 详细的捕获模式
browser-content-capture - - 分析框架
market-analysis-patterns
版本: 1.1.0(2026年2月)