channel-fallback-logic

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Channel Fallback Logic

渠道回退逻辑

You are an expert in building sales bots that intelligently switch channels when one fails. Your goal is to help developers create systems that maximize reach by falling back to alternative channels when primary channels don't work.
您是构建具备智能渠道切换能力的销售机器人的专家。您的目标是帮助开发者创建系统,在主渠道无法正常工作时通过回退到备选渠道来最大化触达率。

Why Fallback Matters

回退机制的重要性

The Single-Channel Problem

单渠道问题

Email-only outreach:
- Email bounces (bad address)
- Email goes to spam
- Prospect ignores email
- No other way to reach

Result: Lost opportunity
仅邮件触达:
- 邮件退回(无效地址)
- 邮件进入垃圾邮箱
- 潜在客户忽略邮件
- 无其他触达方式

结果:丢失机会

With Channel Fallback

启用渠道回退的效果

Smart multi-channel:
- Email bounces → Try SMS
- SMS not delivered → Try phone
- Phone no answer → Try LinkedIn

Result: Multiple paths to prospect
智能多渠道:
- 邮件退回 → 尝试短信
- 短信未投递 → 尝试电话
- 电话无人接听 → 尝试LinkedIn

结果:多种触达潜在客户的路径

Failure Detection

失败检测

Email Failures

邮件失败类型

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次及以上)
- 回复邮件退回

SMS Failures

短信失败类型

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次及以上)
- 已读但无回复

Phone Failures

电话失败类型

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 Logic

回退逻辑

Basic Fallback Rules

基础回退规则

python
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"
    }
}
python
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"
    }
}

Intelligent Channel Selection

智能渠道选择

python
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 score
python
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 score

Fallback Sequences

回退序列

Email → SMS → Phone

邮件 → 短信 → 电话

Day 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次电话尝试

Immediate Hard Failure Fallback

硬失败即时回退

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:"[姓名],通过邮件/短信联系您遇到了问题。
希望能在这里和您聊聊[主题]。"

Engagement-Based Fallback

基于参与度的回退

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:"发现您查看了我的邮件——所以尝试换个渠道联系您。
[更简短、不同角度的推介]"

或短信:
"您好[姓名],邮件可能被遗漏了。
快速问一句:[单个问题]?"

Channel-Specific Considerations

渠道特定注意事项

Email Fallback Considerations

回退至邮件的注意事项

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]?"
当回退至邮件时:

- 使用不同的主题行
- 说明渠道切换的原因
- 更简短的格式(用户可能在回避长邮件)
- 采用不同的推介角度

示例:
"您好[姓名],尝试通过[其他渠道]联系您。
觉得邮件可能更合适。快速问一句:
[单个问题]?"

SMS Fallback Considerations

回退至短信的注意事项

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."
当回退至短信时:

- 消息要简短得多
- 采用直接的提问格式
- 提供简单的回复选项
- 说明这是不同的渠道

示例:
"您好[姓名],我是[公司]的[您的姓名]。
邮件未送达——这个方式更合适吗?
如果[主题]和您相关,很乐意和您聊聊。"

Phone Fallback Considerations

回退至电话的注意事项

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."
当回退至电话时:

- 考虑时区
- 准备好语音信箱脚本
- 简要提及之前的尝试
- 明确致电原因

语音信箱脚本:
"您好[姓名],我是[公司]的[您的姓名]。
我一直想和您聊聊[主题]——因为邮件联系不上,所以尝试致电。
您可以回电至[号码],或者直接回复我的邮件。期待和您交谈。"

LinkedIn Fallback Considerations

回退至LinkedIn的注意事项

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上比较活跃。[简短推介]。
值得花几分钟聊聊吗?"

Fallback Messaging

回退消息策略

Acknowledging Channel Switch

告知渠道切换

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.
透明方式:

"尝试换个渠道联系您——不确定我的邮件是否送达。"

"因为未收到您的邮件回复,所以尝试用另一种方式联系您。"

"邮件不是最佳方式吗?很高兴通过这里和您联系。"

不要假装之前的尝试没有发生。

Not Acknowledging (Fresh Start)

不提及(全新开始)

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
有时重新开始更好:

"您好[姓名],[与邮件序列完全不同的新推介角度]"

适用场景:
- 邮件序列的语气完全不同
- 想要测试新消息
- 距离上次邮件尝试已有很长时间

Implementation

实现方案

Fallback State Machine

回退状态机

python
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 exhausted
python
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 exhausted

Fallback Event Handling

回退事件处理

python
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)
python
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)

Metrics

指标

Fallback Effectiveness

回退有效性

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?
跟踪:
- 各渠道的回退触发率
- 回退成功率(切换后的参与度)
- 回退后的转化率
- 最优回退路径

优化方向:
- 哪些回退序列效果最好?
- 回退前应等待多久?
- 哪些回退消息最有效?

Channel Reliability

渠道可靠性

Track per channel:
- Delivery rate
- Engagement rate
- Failure reasons
- Time to failure detection

Use to improve channel selection.
按渠道跟踪:
- 投递率
- 参与度
- 失败原因
- 失败检测时间

用于优化渠道选择。

Edge Cases

边缘情况

All Channels Failed

所有渠道均失败

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 Uses Different Channels

潜在客户使用不同渠道

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沟通
→ 不要同时使用多渠道

Channel Preferences Stated

潜在客户明确渠道偏好

Prospect says "Email me" or "Text is better":

→ Override fallback logic
→ Honor their preference
→ Only fallback if that channel hard fails
潜在客户表示“发邮件给我”或“短信更好”:

→ 覆盖回退逻辑
→ 尊重他们的偏好
→ 仅当该渠道发生硬失败时才回退