Loading...
Loading...
Compare original and translation side by side
Email-only outreach:
- Email bounces (bad address)
- Email goes to spam
- Prospect ignores email
- No other way to reach
Result: Lost opportunity仅邮件触达:
- 邮件退回(无效地址)
- 邮件进入垃圾邮箱
- 潜在客户忽略邮件
- 无其他触达方式
结果:丢失机会Smart multi-channel:
- Email bounces → Try SMS
- SMS not delivered → Try phone
- Phone no answer → Try LinkedIn
Result: Multiple paths to prospect智能多渠道:
- 邮件退回 → 尝试短信
- 短信未投递 → 尝试电话
- 电话无人接听 → 尝试LinkedIn
结果:多种触达潜在客户的路径Hard failures (don't retry):
- Hard bounce (invalid address)
- Spam complaint
- Unsubscribe
- "Address not found" error
Soft failures (may retry):
- Soft bounce (mailbox full)
- Temporary server error
- Rate limiting
Engagement failures (try other channel):
- Multiple sends, no opens
- Opens but no response (3+)
- Reply-to bounces硬失败(不重试):
- 硬退回(无效地址)
- 垃圾邮件投诉
- 退订
- "地址未找到"错误
软失败(可重试):
- 软退回(邮箱已满)
- 临时服务器错误
- 速率限制
参与度失败(尝试其他渠道):
- 多次发送,无打开记录
- 已打开但无回复(3次及以上)
- 回复邮件退回Hard failures:
- Invalid number
- Landline (can't SMS)
- Carrier block
- Opt-out recorded
Soft failures:
- Temporary delivery failure
- Carrier congestion
- Rate limiting
Engagement failures:
- Delivered but no response (3+)
- Read receipts but no reply硬失败:
- 无效号码
- 固定电话(无法接收短信)
- 运营商拦截
- 已记录退订
软失败:
- 临时投递失败
- 运营商网络拥堵
- 速率限制
参与度失败:
- 已投递但无回复(3次及以上)
- 已读但无回复Hard failures:
- Number disconnected
- Wrong number
- "Do not call" list
Soft failures:
- Voicemail (consider success)
- Busy signal
- No answer
Engagement failures:
- Multiple VM, no callback
- Always goes to VM
- Repeatedly asks to call back but doesn't硬失败:
- 号码已停机
- 错误号码
- 处于"请勿致电"名单
软失败:
- 转入语音信箱(视为成功)
- 占线
- 无人接听
参与度失败:
- 多次留言但未回电
- 始终转入语音信箱
- 多次要求回电但未行动FALLBACK_RULES = {
"email_hard_bounce": {
"fallback_to": ["sms", "phone", "linkedin"],
"delay": timedelta(0), # Immediate
"message": "email_failed_sms_version"
},
"email_no_engagement": {
"fallback_to": ["linkedin"],
"delay": timedelta(days=3),
"condition": "after_3_unopened_emails"
},
"sms_undeliverable": {
"fallback_to": ["email", "phone"],
"delay": timedelta(hours=4),
"message": "sms_failed_email_version"
},
"phone_disconnected": {
"fallback_to": ["email", "linkedin"],
"delay": timedelta(0),
"message": "phone_failed_email_version"
}
}FALLBACK_RULES = {
"email_hard_bounce": {
"fallback_to": ["sms", "phone", "linkedin"],
"delay": timedelta(0), # Immediate
"message": "email_failed_sms_version"
},
"email_no_engagement": {
"fallback_to": ["linkedin"],
"delay": timedelta(days=3),
"condition": "after_3_unopened_emails"
},
"sms_undeliverable": {
"fallback_to": ["email", "phone"],
"delay": timedelta(hours=4),
"message": "sms_failed_email_version"
},
"phone_disconnected": {
"fallback_to": ["email", "linkedin"],
"delay": timedelta(0),
"message": "phone_failed_email_version"
}
}def select_fallback_channel(prospect, failed_channel, failure_type):
# Get available channels for this prospect
available = get_available_channels(prospect)
# Remove failed channel
available.remove(failed_channel)
if not available:
return None
# Prioritize by prospect preferences
if prospect.preferred_channel in available:
return prospect.preferred_channel
# Prioritize by success probability
channel_scores = {}
for channel in available:
score = calculate_channel_score(prospect, channel)
channel_scores[channel] = score
# Return highest scoring available channel
return max(channel_scores, key=channel_scores.get)
def calculate_channel_score(prospect, channel):
score = 50 # Baseline
# Historical engagement
if channel in prospect.engaged_channels:
score += 30
# Channel-specific factors
if channel == "sms" and prospect.mobile_verified:
score += 20
if channel == "linkedin" and prospect.linkedin_active:
score += 15
if channel == "phone" and prospect.answered_before:
score += 25
return scoredef select_fallback_channel(prospect, failed_channel, failure_type):
# Get available channels for this prospect
available = get_available_channels(prospect)
# Remove failed channel
available.remove(failed_channel)
if not available:
return None
# Prioritize by prospect preferences
if prospect.preferred_channel in available:
return prospect.preferred_channel
# Prioritize by success probability
channel_scores = {}
for channel in available:
score = calculate_channel_score(prospect, channel)
channel_scores[channel] = score
# Return highest scoring available channel
return max(channel_scores, key=channel_scores.get)
def calculate_channel_score(prospect, channel):
score = 50 # Baseline
# Historical engagement
if channel in prospect.engaged_channels:
score += 30
# Channel-specific factors
if channel == "sms" and prospect.mobile_verified:
score += 20
if channel == "linkedin" and prospect.linkedin_active:
score += 15
if channel == "phone" and prospect.answered_before:
score += 25
return scoreDay 1: Email #1
Day 3: Email #2 (if no open on #1)
Day 5: Email #3 (if no open on #1 or #2)
After Email #3 with no engagement:
→ Switch to SMS
Day 6: SMS #1
"Hi [Name], I've sent a few emails about [topic].
Not sure if they're getting through—is this a
better way to reach you?"
Day 9: SMS #2 (if no response)
After SMS #2 with no response:
→ Switch to Phone
Day 11: Phone attempt #1
Day 14: Phone attempt #2第1天:发送第1封邮件
第3天:发送第2封邮件(若第1封未被打开)
第5天:发送第3封邮件(若第1或第2封未被打开)
第3封邮件发送后无参与度:
→ 切换至短信
第6天:发送第1条短信
"您好[姓名],我已发送几封关于[主题]的邮件。
不确定您是否收到——这个方式更适合联系您吗?"
第9天:发送第2条短信(若无回复)
第2条短信发送后无回复:
→ 切换至电话
第11天:第1次电话尝试
第14天:第2次电话尝试Email sent → Hard bounce immediately
Fallback response (same day):
SMS: "Hi [Name], email bounced. Trying here
instead. Wanted to reach you about [topic].
Is this the right number?"
If SMS also fails:
LinkedIn: "[Name], having trouble reaching you
via email/text. Would love to connect here
about [topic]."邮件发送 → 立即硬退回
回退响应(当日):
短信:"您好[姓名],邮件退回了。尝试通过这个方式联系您。
想和您聊聊[主题]。这个号码正确吗?"
若短信也失败:
LinkedIn:"[姓名],通过邮件/短信联系您遇到了问题。
希望能在这里和您聊聊[主题]。"Email opened 3x but no response:
Don't retry email—they're seeing but not
responding.
Switch approach:
LinkedIn: "Saw you've been checking out my
emails—figured I'd try a different channel.
[Shorter, different angle pitch]"
Or SMS:
"Hi [Name], emails might be getting lost.
Quick question: [single question]?"邮件被打开3次但无回复:
不再重试邮件——用户已看到但未回应。
切换方式:
LinkedIn:"发现您查看了我的邮件——所以尝试换个渠道联系您。
[更简短、不同角度的推介]"
或短信:
"您好[姓名],邮件可能被遗漏了。
快速问一句:[单个问题]?"When falling back TO email:
- Use different subject line
- Acknowledge channel switch
- Shorter format (they were avoiding long emails)
- Different angle on pitch
Example:
"Hi [Name], tried reaching you on [other channel].
Thought email might be better. Quick question:
[single question]?"当回退至邮件时:
- 使用不同的主题行
- 说明渠道切换的原因
- 更简短的格式(用户可能在回避长邮件)
- 采用不同的推介角度
示例:
"您好[姓名],尝试通过[其他渠道]联系您。
觉得邮件可能更合适。快速问一句:
[单个问题]?"When falling back TO SMS:
- Much shorter message
- Direct question format
- Easy response options
- Acknowledge it's different channel
Example:
"Hi [Name], this is [Your name] from [Company].
Email not getting through—is this better?
Happy to chat if [topic] is relevant."当回退至短信时:
- 消息要简短得多
- 采用直接的提问格式
- 提供简单的回复选项
- 说明这是不同的渠道
示例:
"您好[姓名],我是[公司]的[您的姓名]。
邮件未送达——这个方式更合适吗?
如果[主题]和您相关,很乐意和您聊聊。"When falling back TO phone:
- Consider time zone
- Have voicemail script ready
- Reference other attempts briefly
- Clear reason for call
VM Script:
"Hi [Name], this is [Your name] from [Company].
I've been trying to reach you about [topic]—
wanted to try calling since email didn't connect.
Feel free to call back at [number] or just
reply to my email. Talk soon."当回退至电话时:
- 考虑时区
- 准备好语音信箱脚本
- 简要提及之前的尝试
- 明确致电原因
语音信箱脚本:
"您好[姓名],我是[公司]的[您的姓名]。
我一直想和您聊聊[主题]——因为邮件联系不上,所以尝试致电。
您可以回电至[号码],或者直接回复我的邮件。期待和您交谈。"When falling back TO LinkedIn:
- Check if they're active on LinkedIn
- Keep message professional
- Don't sound desperate about other channels
- New value proposition
Example:
"Hi [Name], reaching out here as LinkedIn seems
to be where you're active. [Brief pitch].
Worth a quick conversation?"当回退至LinkedIn时:
- 确认用户是否在LinkedIn上活跃
- 保持消息专业
- 不要表现出因其他渠道失败而焦虑
- 提供新的价值主张
示例:
"您好[姓名],在这里联系您是因为看起来您在LinkedIn上比较活跃。[简短推介]。
值得花几分钟聊聊吗?"Transparent approach:
"Trying a different channel—not sure if my
emails are getting through."
"Wanted to reach you another way since I
haven't heard back via email."
"Email not the best way? Happy to connect
here instead."
Don't pretend the other attempts didn't happen.透明方式:
"尝试换个渠道联系您——不确定我的邮件是否送达。"
"因为未收到您的邮件回复,所以尝试用另一种方式联系您。"
"邮件不是最佳方式吗?很高兴通过这里和您联系。"
不要假装之前的尝试没有发生。Sometimes better to start fresh:
"Hi [Name], [New pitch angle completely
different from email sequence]"
When to use:
- Email sequence was very different tone
- Want to test new message
- Been a long time since email attempts有时重新开始更好:
"您好[姓名],[与邮件序列完全不同的新推介角度]"
适用场景:
- 邮件序列的语气完全不同
- 想要测试新消息
- 距离上次邮件尝试已有很长时间class ChannelFallback:
def __init__(self, prospect_id):
self.prospect_id = prospect_id
self.attempts = {}
self.current_channel = None
def record_attempt(self, channel, result):
if channel not in self.attempts:
self.attempts[channel] = []
self.attempts[channel].append({
"timestamp": datetime.now(),
"result": result
})
def should_fallback(self, channel):
if channel not in self.attempts:
return False
attempts = self.attempts[channel]
# Hard failure? Immediate fallback
if attempts[-1]["result"] in ["hard_bounce", "invalid", "blocked"]:
return True
# Soft failure pattern? Count
soft_failures = [a for a in attempts if a["result"] in ["no_response", "no_open"]]
if len(soft_failures) >= 3:
return True
return False
def get_next_channel(self):
prospect = get_prospect(self.prospect_id)
for channel in ["email", "sms", "phone", "linkedin"]:
if channel == self.current_channel:
continue
if channel not in self.attempts or not self.should_exhaust(channel):
if is_channel_available(prospect, channel):
return channel
return None # All channels exhaustedclass ChannelFallback:
def __init__(self, prospect_id):
self.prospect_id = prospect_id
self.attempts = {}
self.current_channel = None
def record_attempt(self, channel, result):
if channel not in self.attempts:
self.attempts[channel] = []
self.attempts[channel].append({
"timestamp": datetime.now(),
"result": result
})
def should_fallback(self, channel):
if channel not in self.attempts:
return False
attempts = self.attempts[channel]
# Hard failure? Immediate fallback
if attempts[-1]["result"] in ["hard_bounce", "invalid", "blocked"]:
return True
# Soft failure pattern? Count
soft_failures = [a for a in attempts if a["result"] in ["no_response", "no_open"]]
if len(soft_failures) >= 3:
return True
return False
def get_next_channel(self):
prospect = get_prospect(self.prospect_id)
for channel in ["email", "sms", "phone", "linkedin"]:
if channel == self.current_channel:
continue
if channel not in self.attempts or not self.should_exhaust(channel):
if is_channel_available(prospect, channel):
return channel
return None # All channels exhausteddef handle_channel_event(event):
fallback = ChannelFallback(event.prospect_id)
# Record the attempt
fallback.record_attempt(event.channel, event.result)
# Check if we should fallback
if fallback.should_fallback(event.channel):
next_channel = fallback.get_next_channel()
if next_channel:
# Schedule fallback message
schedule_fallback(
prospect_id=event.prospect_id,
channel=next_channel,
delay=get_fallback_delay(event.result),
message_type=get_fallback_message_type(event.channel, next_channel)
)
else:
# All channels exhausted
mark_prospect_unreachable(event.prospect_id)def handle_channel_event(event):
fallback = ChannelFallback(event.prospect_id)
# Record the attempt
fallback.record_attempt(event.channel, event.result)
# Check if we should fallback
if fallback.should_fallback(event.channel):
next_channel = fallback.get_next_channel()
if next_channel:
# Schedule fallback message
schedule_fallback(
prospect_id=event.prospect_id,
channel=next_channel,
delay=get_fallback_delay(event.result),
message_type=get_fallback_message_type(event.channel, next_channel)
)
else:
# All channels exhausted
mark_prospect_unreachable(event.prospect_id)Track:
- Fallback trigger rate by channel
- Fallback success rate (engagement after switch)
- Conversion rate post-fallback
- Optimal fallback paths
Optimize:
- Which fallback sequences work best?
- How long to wait before fallback?
- Which messages work for fallback?跟踪:
- 各渠道的回退触发率
- 回退成功率(切换后的参与度)
- 回退后的转化率
- 最优回退路径
优化方向:
- 哪些回退序列效果最好?
- 回退前应等待多久?
- 哪些回退消息最有效?Track per channel:
- Delivery rate
- Engagement rate
- Failure reasons
- Time to failure detection
Use to improve channel selection.按渠道跟踪:
- 投递率
- 参与度
- 失败原因
- 失败检测时间
用于优化渠道选择。When every channel has failed:
Options:
1. Mark as unreachable (temporary)
2. Add to long-term reactivation list
3. Try data enrichment (find new contact info)
4. Try different contact at company
"All contact methods exhausted. Adding to
quarterly reactivation list."当所有渠道都失败时:
选项:
1. 标记为暂时无法触达
2. 添加至长期重新激活列表
3. 尝试数据 enrichment(查找新的联系信息)
4. 尝试联系公司内的其他联系人
"所有联系方式均已用尽。添加至季度重新激活列表。"Prospect responds on unexpected channel:
Email sequence running, prospect responds via LinkedIn:
→ Pause email sequence
→ Continue on LinkedIn
→ Don't multi-channel simultaneously潜在客户通过意外渠道回复:
邮件序列正在进行中,潜在客户通过LinkedIn回复:
→ 暂停邮件序列
→ 继续通过LinkedIn沟通
→ 不要同时使用多渠道Prospect says "Email me" or "Text is better":
→ Override fallback logic
→ Honor their preference
→ Only fallback if that channel hard fails潜在客户表示“发邮件给我”或“短信更好”:
→ 覆盖回退逻辑
→ 尊重他们的偏好
→ 仅当该渠道发生硬失败时才回退