首页 全部提示词 Sales

销售研究

Sales Research

技能 @tomstools11 18,593 字符 在 prompts.chat 查看 译文有问题?

中文译文

销售研究

概述

本技能提供研究销售潜在客户的方法论和最佳实践。它涵盖公司研究、联系人画像和信号检测,以呈现可执行的洞察。

用法

company-researcher 和 contact-researcher 子代理在以下情况下引用本技能:

  • 研究新的潜在客户
  • 查找公司信息
  • 为单个联系人建立画像
  • 检测购买信号

研究方法论

公司研究清单

  1. 基本概况

    • 公司名称、行业、规模(员工数、营收)
    • 总部和关键地点
    • 成立日期、成长阶段
  2. 近期动态

    • 融资公告(过去 12 个月)
    • 并购活动
    • 领导层变动
    • 产品发布
  3. 技术栈

    • 已知技术(BuiltWith、StackShare)
    • 提及相关工具的招聘信息
    • 集成合作伙伴关系
  4. 信号

    • 招聘信息(扩张 = 机会)
    • Glassdoor 评价(痛点)
    • 新闻提及(背景)
    • 社交媒体活动

联系人研究清单

  1. 职业背景

    • 当前职位和任期
    • 以往公司和职位
    • 教育背景
  2. 影响力指标

    • 汇报关系
    • 决策权限
    • 预算归属
  3. 互动切入点

    • 近期 LinkedIn 帖子
    • 发表的文章
    • 演讲活动
    • 共同人脉

资源

  • resources/signal-indicators.md - 购买信号分类法
  • resources/research-checklist.md - 完整研究清单

脚本

  • scripts/company-enricher.py - 从多个来源汇总公司数据
  • scripts/linkedin-parser.py - 结构化 LinkedIn 个人资料数据 FILE:company-enricher.py

#!/usr/bin/env python3 """ company-enricher.py - 从多个来源汇总公司数据 输入:

  • company_name: string
  • domain: string(可选)

输出:

  • profile: name: string industry: string size: string funding: string tech_stack: [string] recent_news: [news items]

依赖:

  • requests, beautifulsoup4 """

依赖:requests, beautifulsoup4

import json from typing import Any from dataclasses import dataclass, asdict from datetime import datetime

@dataclass class NewsItem: title: str date: str source: str url: str summary: str

@dataclass class CompanyProfile: name: str domain: str industry: str size: str location: str founded: str funding: str tech_stack: list[str] recent_news: list[dict] competitors: list[str] description: str

def search_company_info(company_name: str, domain: str = None) -> dict: """ 搜索公司的基本信息。 在生产环境中,这里会调用 Clearbit、Crunchbase 等 API。 """ # TODO: 实现实际的 API 调用 # 占位返回结构 return { "name": company_name, "domain": domain or f"{company_name.lower().replace(' ', '')}.com", "industry": "Technology", # 将来自 API "size": "Unknown", "location": "Unknown", "founded": "Unknown", "description": f"Information about {company_name}" }

def search_funding_info(company_name: str) -> dict: """ 搜索融资信息。 在生产环境中,会调用 Crunchbase、PitchBook 等。 """ # TODO: 实现实际的 API 调用 return { "total_funding": "Unknown", "last_round": "Unknown", "last_round_date": "Unknown", "investors": [] }

def search_tech_stack(domain: str) -> list[str]: """ 检测技术栈。 在生产环境中,会调用 BuiltWith、Wappalyzer 等。 """ # TODO: 实现实际的 API 调用 return [] def search_recent_news(company_name: str, days: int = 90) -> list[dict]: """ 搜索关于该公司的近期新闻。 在生产环境中,会调用新闻 API。 """ # TODO: 实现实际的 API 调用 return []

def main( company_name: str, domain: str = None ) -> dict[str, Any]: """ 从多个来源聚合公司数据。

参数:
    company_name: 要调研的公司名称
    domain: 公司域名(可选,将被推断)

返回:
    包含公司概况的 dict,包括行业、规模、融资、技术栈、新闻
"""
# 获取公司基本信息
basic_info = search_company_info(company_name, domain)

# 获取融资信息
funding_info = search_funding_info(company_name)

# 检测技术栈
company_domain = basic_info.get("domain", domain)
tech_stack = search_tech_stack(company_domain) if company_domain else []

# 获取近期新闻
news = search_recent_news(company_name)

# 汇编概况
profile = CompanyProfile(
    name=basic_info["name"],
    domain=basic_info["domain"],
    industry=basic_info["industry"],
    size=basic_info["size"],
    location=basic_info["location"],
    founded=basic_info["founded"],
    funding=funding_info.get("total_funding", "Unknown"),
    tech_stack=tech_stack,
    recent_news=news,
    competitors=[],  # 将从行业分析中补充
    description=basic_info["description"]
)

return {
    "profile": asdict(profile),
    "funding_details": funding_info,
    "enriched_at": datetime.now().isoformat(),
    "sources_checked": ["company_info", "funding", "tech_stack", "news"]
}

if name == "main": import sys

# 示例用法
result = main(
    company_name="DataFlow Systems",
    domain="dataflow.io"
)
print(json.dumps(result, indent=2))

FILE:linkedin-parser.py #!/usr/bin/env python3 """ linkedin-parser.py - 结构化 LinkedIn 个人资料数据 输入:

  • profile_url: string
  • 或 name + company: strings

输出:

  • contact: name: string title: string tenure: string previous_roles: [role objects] mutual_connections: [string] recent_activity: [post summaries]

依赖:

  • requests """

要求:requests

import json from typing import Any from dataclasses import dataclass, asdict from datetime import datetime

@dataclass class PreviousRole: title: str company: str duration: str description: str

@dataclass class RecentPost: date: str content_preview: str engagement: int topic: str

@dataclass class ContactProfile: name: str title: str company: str location: str tenure: str previous_roles: list[dict] education: list[str] mutual_connections: list[str] recent_activity: list[dict] profile_url: str headline: str

def search_linkedin_profile(name: str = None, company: str = None, profile_url: str = None) -> dict: """ 搜索 LinkedIn 个人资料信息。 在生产环境中,会使用 LinkedIn API 或 Sales Navigator。 """ # TODO: 实现实际的 LinkedIn API 集成 # 注意:LinkedIn 的 API 有严格的服务条款

return {
    "found": False,
    "name": name or "Unknown",
    "title": "Unknown",
    "company": company or "Unknown",
    "location": "Unknown",
    "headline": "",
    "tenure": "Unknown",
    "profile_url": profile_url or ""
}

def get_career_history(profile_data: dict) -> list[dict]: """ 从个人资料中提取职业经历。 """ # TODO: 实现职业经历提取 return []

def get_mutual_connections(profile_data: dict, user_network: list = None) -> list[str]: """ 查找共同联系人。 """ # TODO: 实现共同联系人检测 return [] def get_recent_activity(profile_data: dict, days: int = 30) -> list[dict]: """ 获取最近的帖子和活动。 """ # TODO: 实现活动提取 return []

def main( name: str = None, company: str = None, profile_url: str = None ) -> dict[str, Any]: """ 为销售准备整理 LinkedIn 个人资料数据。

参数:
    name: 姓名
    company: 所在公司
    profile_url: LinkedIn 个人资料直接链接

返回:
    包含结构化联系人资料的 dict
"""
if not profile_url and not (name and company):
    return {"error": "请提供 profile_url 或 name + company"}

# 搜索个人资料
profile_data = search_linkedin_profile(
    name=name,
    company=company,
    profile_url=profile_url
)

if not profile_data.get("found"):
    return {
        "found": False,
        "name": name or "Unknown",
        "company": company or "Unknown",
        "message": "未找到个人资料或访问受限",
        "suggestions": [
            "尝试直接在 LinkedIn 上搜索",
            "检查是否有其他拼写方式",
            "确认此人是否仍在该公司工作"
        ]
    }

# 获取职业经历
previous_roles = get_career_history(profile_data)

# 查找共同联系人
mutual_connections = get_mutual_connections(profile_data)

# 获取最近活动
recent_activity = get_recent_activity(profile_data)

# 汇总联系人资料
contact = ContactProfile(
    name=profile_data["name"],
    title=profile_data["title"],
    company=profile_data["company"],
    location=profile_data["location"],
    tenure=profile_data["tenure"],
    previous_roles=previous_roles,
    education=[],  # 将从个人资料中提取
    mutual_connections=mutual_connections,
    recent_activity=recent_activity,
    profile_url=profile_data["profile_url"],
    headline=profile_data["headline"]
)

return { "found": True, "contact": asdict(contact), "research_date": datetime.now().isoformat(), "data_completeness": calculate_completeness(contact) }

def calculate_completeness(contact: ContactProfile) -> dict: """计算资料数据的完整程度。""" fields = { "basic_info": bool(contact.name and contact.title and contact.company), "career_history": len(contact.previous_roles) > 0, "mutual_connections": len(contact.mutual_connections) > 0, "recent_activity": len(contact.recent_activity) > 0, "education": len(contact.education) > 0 }

complete_count = sum(fields.values())
return {
    "fields": fields,
    "score": f"{complete_count}/{len(fields)}",
    "percentage": int((complete_count / len(fields)) * 100)
}

if name == "main": import sys

# 示例用法
result = main(
    name="Sarah Chen",
    company="DataFlow Systems"
)
print(json.dumps(result, indent=2))

FILE:priority-scorer.py #!/usr/bin/env python3 """ priority-scorer.py - 计算并排列潜在客户的优先级

输入:

  • prospects:带有信号的潜在客户对象列表
  • weights:{deal_size, timing, warmth, signals}

输出:

  • ranked:带有评分和理由的潜在客户列表

依赖:

  • (无 - 纯 Python) """

import json from typing import Any from dataclasses import dataclass

默认评分权重

DEFAULT_WEIGHTS = { "deal_size": 0.25, "timing": 0.30, "warmth": 0.20, "signals": 0.25 }

信号评分映射

SIGNAL_SCORES = { # 高意向信号 "recent_funding": 10, "leadership_change": 8, "job_postings_relevant": 9, "expansion_news": 7, "competitor_mention": 6,

# 中等意向信号
"general_hiring": 4,
"industry_event": 3,
"content_engagement": 3,

关系信号

"mutual_connection": 5, "previous_contact": 6, "referred_lead": 8,

负面信号

"recent_layoffs": -3, "budget_freeze_mentioned": -5, "competitor_selected": -7, }

@dataclass class ScoredProspect: company: str contact: str call_time: str raw_score: float normalized_score: int priority_rank: int score_breakdown: dict reasoning: str is_followup: bool

def score_deal_size(prospect: dict) -> tuple[float, str]: """根据预估交易规模评分。""" size_indicators = prospect.get("size_indicators", {})

employee_count = size_indicators.get("employees", 0)
revenue_estimate = size_indicators.get("revenue", 0)

# 基于公司规模的简单评分
if employee_count > 1000 or revenue_estimate > 100_000_000:
    return 10.0, "企业级机会"
elif employee_count > 200 or revenue_estimate > 20_000_000:
    return 7.0, "中端市场机会"
elif employee_count > 50:
    return 5.0, "中小企业机会"
else:
    return 3.0, "小型企业"

def score_timing(prospect: dict) -> tuple[float, str]: """根据时机信号评分。""" timing_signals = prospect.get("timing_signals", [])

score = 5.0  # 基础分数
reasons = []

for signal in timing_signals:
    if signal == "budget_cycle_q4":
        score += 3
        reasons.append("第四季度预算规划")
    elif signal == "contract_expiring":
        score += 4
        reasons.append("合同即将到期")
    elif signal == "active_evaluation":
        score += 5
        reasons.append("正在积极评估")
    elif signal == "just_funded":
        score += 3
        reasons.append("近期获得融资")

return min(score, 10.0), "; ".join(reasons) if reasons else "Standard timing"

def score_warmth(prospect: dict) -> tuple[float, str]: """基于关系热度评分。""" relationship = prospect.get("relationship", {})

if relationship.get("is_followup"):
    last_outcome = relationship.get("last_outcome", "neutral")
    if last_outcome == "positive":
        return 9.0, "Warm follow-up (positive last contact)"
    elif last_outcome == "neutral":
        return 7.0, "Follow-up (neutral last contact)"
    else:
        return 5.0, "Follow-up (needs re-engagement)"

if relationship.get("referred"):
    return 8.0, "Referred lead"

if relationship.get("mutual_connections", 0) > 0:
    return 6.0, f"{relationship['mutual_connections']} mutual connections"

if relationship.get("inbound"):
    return 7.0, "Inbound interest"

return 4.0, "Cold outreach"

def score_signals(prospect: dict) -> tuple[float, str]: """基于检测到的购买信号评分。""" signals = prospect.get("signals", [])

total_score = 0
signal_reasons = []

for signal in signals:
    signal_score = SIGNAL_SCORES.get(signal, 0)
    total_score += signal_score
    if signal_score > 0:
        signal_reasons.append(signal.replace("_", " "))

# Normalize to 0-10 scale
normalized = min(max(total_score / 2, 0), 10)

reason = f"Signals: {', '.join(signal_reasons)}" if signal_reasons else "No strong signals"
return normalized, reason

def calculate_priority_score( prospect: dict, weights: dict = None ) -> ScoredProspect: """计算潜在客户的综合优先级评分。""" weights = weights or DEFAULT_WEIGHTS

# Calculate component scores
deal_score, deal_reason = score_deal_size(prospect)
timing_score, timing_reason = score_timing(prospect)
warmth_score, warmth_reason = score_warmth(prospect)
signal_score, signal_reason = score_signals(prospect)

加权总分

raw_score = (
    deal_score * weights["deal_size"] +
    timing_score * weights["timing"] +
    warmth_score * weights["warmth"] +
    signal_score * weights["signals"]
)

# 汇总理由
reasons = []
if timing_score >= 8:
    reasons.append(timing_reason)
if signal_score >= 7:
    reasons.append(signal_reason)
if warmth_score >= 7:
    reasons.append(warmth_reason)
if deal_score >= 8:
    reasons.append(deal_reason)

return ScoredProspect(
    company=prospect.get("company", "Unknown"),
    contact=prospect.get("contact", "Unknown"),
    call_time=prospect.get("call_time", "Unknown"),
    raw_score=round(raw_score, 2),
    normalized_score=int(raw_score * 10),
    priority_rank=0,  # 将在排序后设置
    score_breakdown={
        "deal_size": {"score": deal_score, "reason": deal_reason},
        "timing": {"score": timing_score, "reason": timing_reason},
        "warmth": {"score": warmth_score, "reason": warmth_reason},
        "signals": {"score": signal_score, "reason": signal_reason}
    },
    reasoning="; ".join(reasons) if reasons else "Standard priority",
    is_followup=prospect.get("relationship", {}).get("is_followup", False)
)

def main( prospects: list[dict], weights: dict = None ) -> dict[str, Any]: """ 计算并排列潜在客户的优先级。

参数:
    prospects:带有信号的潜在客户对象列表
    weights:可选的评分组件自定义权重

返回:
    包含已排序潜在客户和评分详情的字典
"""
weights = weights or DEFAULT_WEIGHTS

# 为所有潜在客户评分
scored = [calculate_priority_score(p, weights) for p in prospects]

按原始分数降序排序

scored.sort(key=lambda x: x.raw_score, reverse=True)

# 分配排名
for i, prospect in enumerate(scored, 1):
    prospect.priority_rank = i

# 转换为字典以便 JSON 序列化
ranked = []
for s in scored:
    ranked.append({
        "company": s.company,
        "contact": s.contact,
        "call_time": s.call_time,
        "priority_rank": s.priority_rank,
        "score": s.normalized_score,
        "reasoning": s.reasoning,
        "is_followup": s.is_followup,
        "breakdown": s.score_breakdown
    })

return {
    "ranked": ranked,
    "weights_used": weights,
    "total_prospects": len(prospects)
}

if name == "main": import sys

# 示例用法
example_prospects = [
    {
        "company": "DataFlow Systems",
        "contact": "Sarah Chen",
        "call_time": "2pm",
        "size_indicators": {"employees": 200, "revenue": 25_000_000},
        "timing_signals": ["just_funded", "active_evaluation"],
        "signals": ["recent_funding", "job_postings_relevant"],
        "relationship": {"is_followup": False, "mutual_connections": 2}
    },
    {
        "company": "Acme Manufacturing",
        "contact": "Tom Bradley",
        "call_time": "10am",
        "size_indicators": {"employees": 500},
        "timing_signals": ["contract_expiring"],
        "signals": [],
        "relationship": {"is_followup": True, "last_outcome": "neutral"}
    },
    {
        "company": "FirstRate Financial",
        "contact": "Linda Thompson",
        "call_time": "4pm",
        "size_indicators": {"employees": 300},
        "timing_signals": [],
        "signals": [],
        "relationship": {"is_followup": False}
    }
]

result = main(prospects=example_prospects) print(json.dumps(result, indent=2)) FILE:research-checklist.md

潜在客户调研清单

公司调研

基本信息

  • 公司名称(核实拼写)
  • 行业/垂直领域
  • 总部所在地
  • 员工人数(LinkedIn、官网)
  • 营收估算(如有)
  • 成立日期
  • 融资阶段/历史

近期新闻(过去 90 天)

  • 融资公告
  • 收购或合并
  • 领导层变动
  • 产品发布
  • 重大客户签约
  • 媒体报道
  • 财报/财务新闻

数字足迹

  • 官网浏览
  • 博客/内容主题
  • 社交媒体存在
  • 招聘信息(招聘页面 + LinkedIn)
  • 技术栈(BuiltWith、招聘信息)

竞争格局

  • 已知竞争对手
  • 市场地位
  • 宣称的差异化优势
  • 近期竞争动作

痛点信号

  • Glassdoor 评价(主题)
  • G2/Capterra 评价(如为 B2B)
  • 社交媒体投诉
  • 招聘信息模式

联系人调研

职业档案

  • 当前职位
  • 任职时长
  • 在职时长
  • 过往公司
  • 过往职位
  • 教育背景

决策权限

  • 汇报对象
  • 团队规模(如为管理者)
  • 预算权限(推断)
  • 采购参与历史

互动切入点

  • 近期 LinkedIn 帖子
  • 发表的文章
  • 播客出镜
  • 会议演讲
  • 共同人脉
  • 共同兴趣/社群

沟通风格

  • 帖子语气(正式/随意)
  • 其互动的话题
  • 回复模式

CRM 检查(如有)

  • 任何既往接触点
  • 过往商机
  • 公司内的相关联系人
  • 同事的备注
  • 邮件互动历史

基于时间的研究深度

可用时间 研究深度
5 分钟 仅公司基本信息 + 联系人职位
15 分钟 + 近期新闻 + LinkedIn 个人资料
30 分钟 + 痛点信号 + 互动切入点
60 分钟 完整清单 + 竞争分析
FILE:signal-indicators.md

信号指标参考

高意向信号

职位发布

  • 发布 3 个以上相关职位 = 主动推进的计划,预算已分配
  • 在你的领域招聘高级人才 = 战略优先级
  • 紧迫性措辞("ASAP"、"immediate") = 痛点非常急迫
  • 提及特定工具 = 了解竞品或品类

财务事件

  • B 轮及以上融资 = 增长资金,购买力
  • IPO 筹备 = 需要运营成熟度
  • 宣布收购 = 即将面临整合挑战
  • 营收里程碑新闻稿 = 预算充足

领导层变动

  • 你的领域新上任 CXO = 90 天优先级设定期
  • 新 CRO/CMO = 可能进行技术栈评估
  • 创始人转任 CEO = 运营专业化

中意向信号

扩张信号

  • 新办公室开设 = 基础设施需求
  • 国际扩张 = 本地化、合规
  • 新产品发布 = 规模化挑战
  • 重大客户签约 = 交付压力

技术信号

  • 发布 RFP = 正在积极采购
  • 提及供应商评估 = 正在比较选购
  • 技术栈变更 = 集成机会
  • 遗留系统抱怨 = 现代化需求

内容信号

  • 发布关于你主题的博客文章 = 正在自我学习
  • 参加网络研讨会 = 兴趣已确认
  • 下载白皮书 = 问题意识
  • 会议演讲 = 思想领导力,曝光度

低意向信号(培育)

一般活动

  • 行业活动出席 = 市场参与者
  • 通用招聘 = 公司正在成长
  • 正面媒体报道 = 公司健康
  • 社交媒体活动 = 领导层积极参与

信号评分

信号类型 分数 行动
职位发布(相关) +3 优先外联
近期融资 +3 在对话中提及
领导层变动 +2 时效性机会
扩张新闻 +2 增长角度
负面评价 +2 痛点角度
内容互动 +1 培育轨道
无信号 0 聚焦探索

English original

Sales Research

Overview

This skill provides methodology and best practices for researching sales prospects. It covers company research, contact profiling, and signal detection to surface actionable intelligence.

Usage

The company-researcher and contact-researcher sub-agents reference this skill when:

  • Researching new prospects
  • Finding company information
  • Profiling individual contacts
  • Detecting buying signals

Research Methodology

Company Research Checklist

  1. Basic Profile

    • Company name, industry, size (employees, revenue)
    • Headquarters and key locations
    • Founded date, growth stage
  2. Recent Developments

    • Funding announcements (last 12 months)
    • M&A activity
    • Leadership changes
    • Product launches
  3. Tech Stack

    • Known technologies (BuiltWith, StackShare)
    • Job postings mentioning tools
    • Integration partnerships
  4. Signals

    • Job postings (scaling = opportunity)
    • Glassdoor reviews (pain points)
    • News mentions (context)
    • Social media activity

Contact Research Checklist

  1. Professional Background

    • Current role and tenure
    • Previous companies and roles
    • Education
  2. Influence Indicators

    • Reporting structure
    • Decision-making authority
    • Budget ownership
  3. Engagement Hooks

    • Recent LinkedIn posts
    • Published articles
    • Speaking engagements
    • Mutual connections

Resources

  • resources/signal-indicators.md - Taxonomy of buying signals
  • resources/research-checklist.md - Complete research checklist

Scripts

  • scripts/company-enricher.py - Aggregate company data from multiple sources
  • scripts/linkedin-parser.py - Structure LinkedIn profile data FILE:company-enricher.py

#!/usr/bin/env python3 """ company-enricher.py - Aggregate company data from multiple sources

Inputs:

  • company_name: string
  • domain: string (optional)

Outputs:

  • profile: name: string industry: string size: string funding: string tech_stack: [string] recent_news: [news items]

Dependencies:

  • requests, beautifulsoup4 """

Requirements: requests, beautifulsoup4

import json from typing import Any from dataclasses import dataclass, asdict from datetime import datetime

@dataclass class NewsItem: title: str date: str source: str url: str summary: str

@dataclass class CompanyProfile: name: str domain: str industry: str size: str location: str founded: str funding: str tech_stack: list[str] recent_news: list[dict] competitors: list[str] description: str

def search_company_info(company_name: str, domain: str = None) -> dict: """ Search for basic company information. In production, this would call APIs like Clearbit, Crunchbase, etc. """ # TODO: Implement actual API calls # Placeholder return structure return { "name": company_name, "domain": domain or f"{company_name.lower().replace(' ', '')}.com", "industry": "Technology", # Would come from API "size": "Unknown", "location": "Unknown", "founded": "Unknown", "description": f"Information about {company_name}" }

def search_funding_info(company_name: str) -> dict: """ Search for funding information. In production, would call Crunchbase, PitchBook, etc. """ # TODO: Implement actual API calls return { "total_funding": "Unknown", "last_round": "Unknown", "last_round_date": "Unknown", "investors": [] }

def search_tech_stack(domain: str) -> list[str]: """ Detect technology stack. In production, would call BuiltWith, Wappalyzer, etc. """ # TODO: Implement actual API calls return []

def search_recent_news(company_name: str, days: int = 90) -> list[dict]: """ Search for recent news about the company. In production, would call news APIs. """ # TODO: Implement actual API calls return []

def main( company_name: str, domain: str = None ) -> dict[str, Any]: """ Aggregate company data from multiple sources.

Args:
    company_name: Company name to research
    domain: Company domain (optional, will be inferred)

Returns:
    dict with company profile including industry, size, funding, tech stack, news
"""
# Get basic company info
basic_info = search_company_info(company_name, domain)

# Get funding information
funding_info = search_funding_info(company_name)

# Detect tech stack
company_domain = basic_info.get("domain", domain)
tech_stack = search_tech_stack(company_domain) if company_domain else []

# Get recent news
news = search_recent_news(company_name)

# Compile profile
profile = CompanyProfile(
    name=basic_info["name"],
    domain=basic_info["domain"],
    industry=basic_info["industry"],
    size=basic_info["size"],
    location=basic_info["location"],
    founded=basic_info["founded"],
    funding=funding_info.get("total_funding", "Unknown"),
    tech_stack=tech_stack,
    recent_news=news,
    competitors=[],  # Would be enriched from industry analysis
    description=basic_info["description"]
)

return {
    "profile": asdict(profile),
    "funding_details": funding_info,
    "enriched_at": datetime.now().isoformat(),
    "sources_checked": ["company_info", "funding", "tech_stack", "news"]
}

if name == "main": import sys

# Example usage
result = main(
    company_name="DataFlow Systems",
    domain="dataflow.io"
)
print(json.dumps(result, indent=2))

FILE:linkedin-parser.py #!/usr/bin/env python3 """ linkedin-parser.py - Structure LinkedIn profile data

Inputs:

  • profile_url: string
  • or name + company: strings

Outputs:

  • contact: name: string title: string tenure: string previous_roles: [role objects] mutual_connections: [string] recent_activity: [post summaries]

Dependencies:

  • requests """

Requirements: requests

import json from typing import Any from dataclasses import dataclass, asdict from datetime import datetime

@dataclass class PreviousRole: title: str company: str duration: str description: str

@dataclass class RecentPost: date: str content_preview: str engagement: int topic: str

@dataclass class ContactProfile: name: str title: str company: str location: str tenure: str previous_roles: list[dict] education: list[str] mutual_connections: list[str] recent_activity: list[dict] profile_url: str headline: str

def search_linkedin_profile(name: str = None, company: str = None, profile_url: str = None) -> dict: """ Search for LinkedIn profile information. In production, would use LinkedIn API or Sales Navigator. """ # TODO: Implement actual LinkedIn API integration # Note: LinkedIn's API has strict terms of service

return {
    "found": False,
    "name": name or "Unknown",
    "title": "Unknown",
    "company": company or "Unknown",
    "location": "Unknown",
    "headline": "",
    "tenure": "Unknown",
    "profile_url": profile_url or ""
}

def get_career_history(profile_data: dict) -> list[dict]: """ Extract career history from profile. """ # TODO: Implement career extraction return []

def get_mutual_connections(profile_data: dict, user_network: list = None) -> list[str]: """ Find mutual connections. """ # TODO: Implement mutual connection detection return []

def get_recent_activity(profile_data: dict, days: int = 30) -> list[dict]: """ Get recent posts and activity. """ # TODO: Implement activity extraction return []

def main( name: str = None, company: str = None, profile_url: str = None ) -> dict[str, Any]: """ Structure LinkedIn profile data for sales prep.

Args:
    name: Person's name
    company: Company they work at
    profile_url: Direct LinkedIn profile URL

Returns:
    dict with structured contact profile
"""
if not profile_url and not (name and company):
    return {"error": "Provide either profile_url or name + company"}

# Search for profile
profile_data = search_linkedin_profile(
    name=name,
    company=company,
    profile_url=profile_url
)

if not profile_data.get("found"):
    return {
        "found": False,
        "name": name or "Unknown",
        "company": company or "Unknown",
        "message": "Profile not found or limited access",
        "suggestions": [
            "Try searching directly on LinkedIn",
            "Check for alternative spellings",
            "Verify the person still works at this company"
        ]
    }

# Get career history
previous_roles = get_career_history(profile_data)

# Find mutual connections
mutual_connections = get_mutual_connections(profile_data)

# Get recent activity
recent_activity = get_recent_activity(profile_data)

# Compile contact profile
contact = ContactProfile(
    name=profile_data["name"],
    title=profile_data["title"],
    company=profile_data["company"],
    location=profile_data["location"],
    tenure=profile_data["tenure"],
    previous_roles=previous_roles,
    education=[],  # Would be extracted from profile
    mutual_connections=mutual_connections,
    recent_activity=recent_activity,
    profile_url=profile_data["profile_url"],
    headline=profile_data["headline"]
)

return {
    "found": True,
    "contact": asdict(contact),
    "research_date": datetime.now().isoformat(),
    "data_completeness": calculate_completeness(contact)
}

def calculate_completeness(contact: ContactProfile) -> dict: """Calculate how complete the profile data is.""" fields = { "basic_info": bool(contact.name and contact.title and contact.company), "career_history": len(contact.previous_roles) > 0, "mutual_connections": len(contact.mutual_connections) > 0, "recent_activity": len(contact.recent_activity) > 0, "education": len(contact.education) > 0 }

complete_count = sum(fields.values())
return {
    "fields": fields,
    "score": f"{complete_count}/{len(fields)}",
    "percentage": int((complete_count / len(fields)) * 100)
}

if name == "main": import sys

# Example usage
result = main(
    name="Sarah Chen",
    company="DataFlow Systems"
)
print(json.dumps(result, indent=2))

FILE:priority-scorer.py #!/usr/bin/env python3 """ priority-scorer.py - Calculate and rank prospect priorities

Inputs:

  • prospects: [prospect objects with signals]
  • weights: {deal_size, timing, warmth, signals}

Outputs:

  • ranked: [prospects with scores and reasoning]

Dependencies:

  • (none - pure Python) """

import json from typing import Any from dataclasses import dataclass

Default scoring weights

DEFAULT_WEIGHTS = { "deal_size": 0.25, "timing": 0.30, "warmth": 0.20, "signals": 0.25 }

Signal score mapping

SIGNAL_SCORES = { # High-intent signals "recent_funding": 10, "leadership_change": 8, "job_postings_relevant": 9, "expansion_news": 7, "competitor_mention": 6,

# Medium-intent signals
"general_hiring": 4,
"industry_event": 3,
"content_engagement": 3,

# Relationship signals
"mutual_connection": 5,
"previous_contact": 6,
"referred_lead": 8,

# Negative signals
"recent_layoffs": -3,
"budget_freeze_mentioned": -5,
"competitor_selected": -7,

}

@dataclass class ScoredProspect: company: str contact: str call_time: str raw_score: float normalized_score: int priority_rank: int score_breakdown: dict reasoning: str is_followup: bool

def score_deal_size(prospect: dict) -> tuple[float, str]: """Score based on estimated deal size.""" size_indicators = prospect.get("size_indicators", {})

employee_count = size_indicators.get("employees", 0)
revenue_estimate = size_indicators.get("revenue", 0)

# Simple scoring based on company size
if employee_count > 1000 or revenue_estimate > 100_000_000:
    return 10.0, "Enterprise-scale opportunity"
elif employee_count > 200 or revenue_estimate > 20_000_000:
    return 7.0, "Mid-market opportunity"
elif employee_count > 50:
    return 5.0, "SMB opportunity"
else:
    return 3.0, "Small business"

def score_timing(prospect: dict) -> tuple[float, str]: """Score based on timing signals.""" timing_signals = prospect.get("timing_signals", [])

score = 5.0  # Base score
reasons = []

for signal in timing_signals:
    if signal == "budget_cycle_q4":
        score += 3
        reasons.append("Q4 budget planning")
    elif signal == "contract_expiring":
        score += 4
        reasons.append("Contract expiring soon")
    elif signal == "active_evaluation":
        score += 5
        reasons.append("Actively evaluating")
    elif signal == "just_funded":
        score += 3
        reasons.append("Recently funded")

return min(score, 10.0), "; ".join(reasons) if reasons else "Standard timing"

def score_warmth(prospect: dict) -> tuple[float, str]: """Score based on relationship warmth.""" relationship = prospect.get("relationship", {})

if relationship.get("is_followup"):
    last_outcome = relationship.get("last_outcome", "neutral")
    if last_outcome == "positive":
        return 9.0, "Warm follow-up (positive last contact)"
    elif last_outcome == "neutral":
        return 7.0, "Follow-up (neutral last contact)"
    else:
        return 5.0, "Follow-up (needs re-engagement)"

if relationship.get("referred"):
    return 8.0, "Referred lead"

if relationship.get("mutual_connections", 0) > 0:
    return 6.0, f"{relationship['mutual_connections']} mutual connections"

if relationship.get("inbound"):
    return 7.0, "Inbound interest"

return 4.0, "Cold outreach"

def score_signals(prospect: dict) -> tuple[float, str]: """Score based on buying signals detected.""" signals = prospect.get("signals", [])

total_score = 0
signal_reasons = []

for signal in signals:
    signal_score = SIGNAL_SCORES.get(signal, 0)
    total_score += signal_score
    if signal_score > 0:
        signal_reasons.append(signal.replace("_", " "))

# Normalize to 0-10 scale
normalized = min(max(total_score / 2, 0), 10)

reason = f"Signals: {', '.join(signal_reasons)}" if signal_reasons else "No strong signals"
return normalized, reason

def calculate_priority_score( prospect: dict, weights: dict = None ) -> ScoredProspect: """Calculate overall priority score for a prospect.""" weights = weights or DEFAULT_WEIGHTS

# Calculate component scores
deal_score, deal_reason = score_deal_size(prospect)
timing_score, timing_reason = score_timing(prospect)
warmth_score, warmth_reason = score_warmth(prospect)
signal_score, signal_reason = score_signals(prospect)

# Weighted total
raw_score = (
    deal_score * weights["deal_size"] +
    timing_score * weights["timing"] +
    warmth_score * weights["warmth"] +
    signal_score * weights["signals"]
)

# Compile reasoning
reasons = []
if timing_score >= 8:
    reasons.append(timing_reason)
if signal_score >= 7:
    reasons.append(signal_reason)
if warmth_score >= 7:
    reasons.append(warmth_reason)
if deal_score >= 8:
    reasons.append(deal_reason)

return ScoredProspect(
    company=prospect.get("company", "Unknown"),
    contact=prospect.get("contact", "Unknown"),
    call_time=prospect.get("call_time", "Unknown"),
    raw_score=round(raw_score, 2),
    normalized_score=int(raw_score * 10),
    priority_rank=0,  # Will be set after sorting
    score_breakdown={
        "deal_size": {"score": deal_score, "reason": deal_reason},
        "timing": {"score": timing_score, "reason": timing_reason},
        "warmth": {"score": warmth_score, "reason": warmth_reason},
        "signals": {"score": signal_score, "reason": signal_reason}
    },
    reasoning="; ".join(reasons) if reasons else "Standard priority",
    is_followup=prospect.get("relationship", {}).get("is_followup", False)
)

def main( prospects: list[dict], weights: dict = None ) -> dict[str, Any]: """ Calculate and rank prospect priorities.

Args:
    prospects: List of prospect objects with signals
    weights: Optional custom weights for scoring components

Returns:
    dict with ranked prospects and scoring details
"""
weights = weights or DEFAULT_WEIGHTS

# Score all prospects
scored = [calculate_priority_score(p, weights) for p in prospects]

# Sort by raw score descending
scored.sort(key=lambda x: x.raw_score, reverse=True)

# Assign ranks
for i, prospect in enumerate(scored, 1):
    prospect.priority_rank = i

# Convert to dicts for JSON serialization
ranked = []
for s in scored:
    ranked.append({
        "company": s.company,
        "contact": s.contact,
        "call_time": s.call_time,
        "priority_rank": s.priority_rank,
        "score": s.normalized_score,
        "reasoning": s.reasoning,
        "is_followup": s.is_followup,
        "breakdown": s.score_breakdown
    })

return {
    "ranked": ranked,
    "weights_used": weights,
    "total_prospects": len(prospects)
}

if name == "main": import sys

# Example usage
example_prospects = [
    {
        "company": "DataFlow Systems",
        "contact": "Sarah Chen",
        "call_time": "2pm",
        "size_indicators": {"employees": 200, "revenue": 25_000_000},
        "timing_signals": ["just_funded", "active_evaluation"],
        "signals": ["recent_funding", "job_postings_relevant"],
        "relationship": {"is_followup": False, "mutual_connections": 2}
    },
    {
        "company": "Acme Manufacturing",
        "contact": "Tom Bradley",
        "call_time": "10am",
        "size_indicators": {"employees": 500},
        "timing_signals": ["contract_expiring"],
        "signals": [],
        "relationship": {"is_followup": True, "last_outcome": "neutral"}
    },
    {
        "company": "FirstRate Financial",
        "contact": "Linda Thompson",
        "call_time": "4pm",
        "size_indicators": {"employees": 300},
        "timing_signals": [],
        "signals": [],
        "relationship": {"is_followup": False}
    }
]

result = main(prospects=example_prospects)
print(json.dumps(result, indent=2))

FILE:research-checklist.md

Prospect Research Checklist

Company Research

Basic Information

  • Company name (verify spelling)
  • Industry/vertical
  • Headquarters location
  • Employee count (LinkedIn, website)
  • Revenue estimate (if available)
  • Founded date
  • Funding stage/history

Recent News (Last 90 Days)

  • Funding announcements
  • Acquisitions or mergers
  • Leadership changes
  • Product launches
  • Major customer wins
  • Press mentions
  • Earnings/financial news

Digital Footprint

  • Website review
  • Blog/content topics
  • Social media presence
  • Job postings (careers page + LinkedIn)
  • Tech stack (BuiltWith, job postings)

Competitive Landscape

  • Known competitors
  • Market position
  • Differentiators claimed
  • Recent competitive moves

Pain Point Indicators

  • Glassdoor reviews (themes)
  • G2/Capterra reviews (if B2B)
  • Social media complaints
  • Job posting patterns

Contact Research

Professional Profile

  • Current title
  • Time in role
  • Time at company
  • Previous companies
  • Previous roles
  • Education

Decision Authority

  • Reports to whom
  • Team size (if manager)
  • Budget authority (inferred)
  • Buying involvement history

Engagement Hooks

  • Recent LinkedIn posts
  • Published articles
  • Podcast appearances
  • Conference talks
  • Mutual connections
  • Shared interests/groups

Communication Style

  • Post tone (formal/casual)
  • Topics they engage with
  • Response patterns

CRM Check (If Available)

  • Any prior touchpoints
  • Previous opportunities
  • Related contacts at company
  • Notes from colleagues
  • Email engagement history

Time-Based Research Depth

Time Available Research Depth
5 minutes Company basics + contact title only
15 minutes + Recent news + LinkedIn profile
30 minutes + Pain point signals + engagement hooks
60 minutes Full checklist + competitive analysis
FILE:signal-indicators.md

Signal Indicators Reference

High-Intent Signals

Job Postings

  • 3+ relevant roles posted = Active initiative, budget allocated
  • Senior hire in your domain = Strategic priority
  • Urgency language ("ASAP", "immediate") = Pain is acute
  • Specific tool mentioned = Competitor or category awareness

Financial Events

  • Series B+ funding = Growth capital, buying power
  • IPO preparation = Operational maturity needed
  • Acquisition announced = Integration challenges coming
  • Revenue milestone PR = Budget available

Leadership Changes

  • New CXO in your domain = 90-day priority setting
  • New CRO/CMO = Tech stack evaluation likely
  • Founder transition to CEO = Professionalizing operations

Medium-Intent Signals

Expansion Signals

  • New office opening = Infrastructure needs
  • International expansion = Localization, compliance
  • New product launch = Scaling challenges
  • Major customer win = Delivery pressure

Technology Signals

  • RFP published = Active buying process
  • Vendor review mentioned = Comparison shopping
  • Tech stack change = Integration opportunity
  • Legacy system complaints = Modernization need

Content Signals

  • Blog post on your topic = Educating themselves
  • Webinar attendance = Interest confirmed
  • Whitepaper download = Problem awareness
  • Conference speaking = Thought leadership, visibility

Low-Intent Signals (Nurture)

General Activity

  • Industry event attendance = Market participant
  • Generic hiring = Company growing
  • Positive press = Healthy company
  • Social media activity = Engaged leadership

Signal Scoring

Signal Type Score Action
Job posting (relevant) +3 Prioritize outreach
Recent funding +3 Reference in conversation
Leadership change +2 Time-sensitive opportunity
Expansion news +2 Growth angle
Negative reviews +2 Pain point angle
Content engagement +1 Nurture track
No signals 0 Discovery focus