用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/dvcrn/openclaw-skills-marketplace --skill competitor-finder-adarsh命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | competitor-finder-adarsh |
| description | Competitor Finder Adarsh |
Identifies 3-5 competitors for a given brand by searching the web via SerpAPI and, as a last resort, falling back to a minimal OpenAI call. Returns competitor names, websites, and optionally the reason they are considered competitors. This collector feeds into the Marketing Audit Pipeline to populate the Competitor Landscape section of the final report.
// Function signature
collectCompetitors(brandName: string, domain?: string): Promise<CompetitorData>
// brandName: The brand name to find competitors for (e.g. "Gymshark")
// domain: Optional domain for additional context (e.g. "gymshark.com").
// Helps refine competitor search and filter out the brand itself from results.
interface CompetitorData {
competitors: CompetitorEntry[]; // 3-5 competitor entries
error?: string; // Present only when collector fails
}
interface CompetitorEntry {
name: string; // e.g. "Nike"
website: string; // e.g. "nike.com"
reason?: string; // e.g. "Direct competitor in activewear market"
}
https://serpapi.com/search.jsonSERPAPI_KEY environment variablehttps://api.dataforseo.com/v3/dataforseo_labs/google/competitors_domain/liveDATAFORSEO_LOGIN + DATAFORSEO_PASSWORD environment variablesgpt-4.1-miniOPENAI_API_KEY environment variablebrandName and optional domain from the pipelineCompetitorData// Query: "top competitors of {brandName}"
{
api_key: process.env.SERPAPI_KEY,
engine: "google",
q: `top competitors of ${brandName}`,
num: 10
}
[{
target: domain, // e.g. "gymshark.com"
language_code: "en",
location_code: 2840, // United States
limit: 5
}]
// ONLY used when Methods 1 and 2 both fail
// This is a MINIMAL prompt -- keep token usage as low as possible
const response = await openai.chat.completions.create({
model: 'gpt-4.1-mini',
max_tokens: 200,
temperature: 0.3,
messages: [
{
role: 'system',
content: 'You are a marketing analyst. Return only a JSON array of competitor objects.'
},
{
role: 'user',
content: `List 5 direct competitors of "${brandName}"${domain ? ` (${domain})` : ''}. Return JSON: [{"name":"...","website":"...","reason":"..."}]`
}
]
});
name and website populatedtry/catchEMPTY_COMPETITOR_DATA with error field set:return { ...EMPTY_COMPETITOR_DATA, error: 'Competitor data unavailable: <reason>' };
CompetitorData objectlogger.error('Competitor collector failed', { brandName, domain, method, err });
logger.warn('Competitor finder: SerpAPI failed, falling back to DataForSEO', { brandName });
logger.warn('Competitor finder: DataForSEO failed, falling back to OpenAI', { brandName });
import { collectCompetitors } from '../collectors/competitorCollector';
// Successful collection (via SerpAPI)
const data = await collectCompetitors('Gymshark', 'gymshark.com');
// Returns:
// {
// competitors: [
// { name: "Nike", website: "nike.com", reason: "Global leader in athletic apparel" },
// { name: "Lululemon", website: "lululemon.com", reason: "Premium activewear competitor" },
// { name: "Under Armour", website: "underarmour.com", reason: "Direct competitor in gym wear" },
// { name: "Alphalete", website: "alphalete.com", reason: "DTC fitness apparel brand" },
// { name: "Fabletics", website: "fabletics.com", reason: "Subscription-based activewear" },
// ],
// }
// Partial result (only OpenAI fallback worked)
const partial = await collectCompetitors('ObscureBrand');
// Returns:
// {
// competitors: [
// { name: "CompetitorA", website: "competitora.com", reason: "Similar product category" },
// { name: "CompetitorB", website: "competitorb.com", reason: "Same target market" },
// { name: "CompetitorC", website: "competitorc.com" },
// ],
// }
// Failed collection (graceful degradation)
const failedData = await collectCompetitors('UnknownBrand');
// Returns:
// {
// competitors: [],
reportGenerator.ts where an AI model call is permitted. It must be minimal (max 200 tokens) and should be logged as a warning for cost monitoring.'instagram' (no domain available), skip Method 2 (DataForSEO requires a domain) and rely on Methods 1 and 3.EMPTY_COMPETITOR_DATA constant is defined in src/types/audit.types.ts and should be imported for fallback returns.