本文目录导读:

用PHP实现用户召回,通常指通过主动触达(如邮件、短信、推送)重新激活已流失或沉睡的用户,一个完整的PHP用户召回系统通常包括:用户分群、触达渠道、内容生成和效果追踪。
下面是一个从基础到落地的实现方案,包含代码示例和关键逻辑。
核心流程架构
系统调度 (Cron) -> 用户分群分析 -> 生成召回策略 -> 发送触达 (Mail/SMS/App Push) -> 效果追踪 (点击/登录)
第一步:用户分群与数据准备
不是所有用户都需要被召回,需要定义 “沉睡用户” 的标准(连续30天未登录,或注册后7天内无订单),这需要在PHP中进行数据查询和逻辑判断。
// 示例:查询出需要召回的“沉睡用户”
class UserRecallService {
private $db;
public function __construct($pdo) {
$this->db = $pdo;
}
/**
* 获取需要召回的沉睡用户列表
* @param int $days 定义多少天未登录算沉睡
* @return array
*/
public function getSleepingUsers(int $days = 30): array {
$sql = "SELECT id, email, phone, username, last_login_at
FROM users
WHERE status = 1
AND last_login_at IS NOT NULL
AND last_login_at < NOW() - INTERVAL :days DAY
AND (last_recall_at IS NULL OR last_recall_at < NOW() - INTERVAL 7 DAY) -- 避免过度召回
ORDER BY last_login_at ASC
LIMIT 1000"; // 分批处理,防止内存溢出
$stmt = $this->db->prepare($sql);
$stmt->execute(['days' => $days]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}
优化点:
- 使用
last_recall_at字段控制召回频率(7天内不重复召回)。 - 加上
LIMIT分页,通过Cron循环处理大批量用户。 - 可以结合用户行为标签(如:下单用户、浏览用户)生成更精准的分群。
第二步:生成召回内容(个性化模板)
必须具备个性化和吸引力,PHP可以通过模板引擎或字符串替换实现。
class RecallContentGenerator {
/**
* 根据用户数据和召回策略生成内容
* @param array $user 用户数据
* @param string $type 'email' | 'sms'
* @return array ['title' => string, 'content' => string]
*/
public function generate(array $user, string $type = 'email'): array {
$username = $user['username'] ?? '用户';
$promotion = $this->getRandomCoupon(); // 获取一个优惠券代码(从数据库或Redis获取)
if ($type === 'email') {
$title = "{$username},你有一张专属优惠券待领取!";
$content = "亲爱的{$username},好久不见!我们为您准备了一张价值{$promotion['value']}元的优惠券,有效期至本周日。\n点击链接领取:https://yourdomain.com/reclaim?code={$promotion['code']}&uid={$user['id']}";
} else { // SMS短信用简洁内容
$title = ''; // SMS一般无标题
$content = "【YourApp】{$username},您有专属优惠券{$promotion['value']}元,点击领取:https://yourdomain.com/reclaim?code={$promotion['code']}&uid={$user['id']}";
}
return ['title' => $title, 'content' => $content];
}
private function getRandomCoupon(): array {
// 实际项目中从数据库获取一个未被领取的优惠券
return ['code' => 'WELCOME2023', 'value' => 20];
}
}
关键点:
- 使用
uid和code生成唯一追踪链接。 - 对于短信,由于长度限制,必须包含短链和关键行动号召(CTA)。
- 对于邮件,可以嵌入HTML模板。
第三步:选择触达渠道并发送
PHP原生支持 mail(),但生产环境建议使用第三方SDK(如阿里云短信、SendGrid、极光推送)。
// 使用抽象接口方便扩展
interface MessengerInterface {
public function send(string $recipient, string $title, string $content): bool;
}
class EmailMessenger implements MessengerInterface {
public function send(string $recipient, string $title, string $content): bool {
// 使用 PHPMailer 或 SendGrid SDK
// 简化示例:
$headers = "From: recall@yourdomain.com\r\n";
return mail($recipient, $title, $content, $headers);
}
}
class SMSMessenger implements MessengerInterface {
public function send(string $recipient, string $title, string $content): bool {
// 调用阿里云短信API、Twilio等
// 假设已配置好 $smsClient
// return $smsClient->sendSms($recipient, $content);
return true; // 模拟成功
}
}
// 发送器
class RecallSender {
private array $messengers;
public function __construct() {
$this->messengers = [
'email' => new EmailMessenger(),
'sms' => new SMSMessenger(),
];
}
/**
* 执行单次发送并记录日志
*/
public function sendRecall(array $user, string $channel): bool {
$generator = new RecallContentGenerator();
$content = $generator->generate($user, $channel);
$recipient = ($channel === 'email') ? $user['email'] : $user['phone'];
if (empty($recipient)) {
return false;
}
$success = $this->messengers[$channel]->send($recipient, $content['title'], $content['content']);
// 更新用户的召回记录
if ($success) {
$this->logRecall($user['id'], $channel, $content['title']);
}
return $success;
}
private function logRecall(int $userId, string $channel, string $message): void {
// 写入数据库 recall_log 表:user_id, channel, sent_at, message_content
}
}
第四步:效果追踪(核心环节)
没有追踪的召回是盲目的,我们需要追踪用户点击链接和最终登录/转化。
1 追踪链接处理
在 reclaim.php 中处理用户点击:
// reclaim.php (短链或支付页)
$code = $_GET['code'] ?? '';
$uid = (int)($_GET['uid'] ?? 0);
if ($uid > 0 && !empty($code)) {
// 记录点击事件
$logSql = "INSERT INTO recall_click_log (user_id, coupon_code, clicked_at) VALUES (:uid, :code, NOW())";
// ... 执行SQL ...
// 标记用户为“已点击”
$updateSql = "UPDATE users SET last_recall_clicked_at = NOW() WHERE id = :uid";
// ... 执行SQL ...
// 发放优惠券并重定向到优惠券落地页
// header("Location: /coupon/redeem?code=" . urlencode($code));
exit("召回成功!优惠券已发放到您的账户。");
}
2 最终转化追踪
在用户登录或下单时检查 last_recall_clicked_at 字段:
// 在用户登录成功后的逻辑中
if (!empty($user['last_recall_clicked_at']) && empty($user['last_recall_converted_at'])) {
// 标记用户已转化(召回成功)
$updateSql = "UPDATE users SET last_recall_converted_at = NOW() WHERE id = :uid";
// ... 执行SQL ...
}
3 数据报表
-- 查询召回效果 SELECT COUNT(DISTINCT user_id) as total_recalled, -- 总召回发送人数 SUM(CASE WHEN last_recall_clicked_at IS NOT NULL THEN 1 ELSE 0 END) as total_clicks, -- 点击人数 SUM(CASE WHEN last_recall_converted_at IS NOT NULL THEN 1 ELSE 0 END) as total_converted -- 转化人数 FROM users WHERE last_recall_at IS NOT NULL;
第五步:调度与防骚扰(Cron + 限流)
在Linux服务器上设置Cron任务:
# 每天凌晨2点执行批量召回 0 2 * * * /usr/bin/php /path/to/your_project/artisan recall:execute
PHP命令行脚本:
// artisian recall:execute (通过CLI运行)
$recallService = new UserRecallService($pdo);
$sender = new RecallSender();
$sleepingUsers = $recallService->getSleepingUsers(30); // 30天未登录
foreach ($sleepingUsers as $user) {
// 根据用户类型选择渠道:有邮箱用邮件,无邮箱用短信
$channel = !empty($user['email']) ? 'email' : 'sms';
$sender->sendRecall($user, $channel);
// 每发100个暂停1秒,防止被限流
if ($i % 100 === 0) {
sleep(1);
}
}
进阶优化建议
- A/B测试:将用户随机分为A/B组,测试不同的标题、优惠券金额、发送时间。
- 多波次策略:第一波发邮件,3天无点击再发短信,7天无转化再发Push,记录每个波次的时间戳。
- 避免垃圾邮件:使用SPF、DKIM签名,并检查用户是否退订(
unsubscribed字段)。 - 使用消息队列:如果用户量很大(>10万),将发送任务写入Redis队列,由多个Worker消费,防止Cron超时。
- 合规性:确认用户是否同意接收营销信息,并在邮件/短信中添加“退订”链接。
PHP实现用户召回的核心思路是:
- 分人(沉睡定义) -> 给饵(个性化优惠) -> 触达(多渠道) -> 追踪(点击/登录) -> 优化(A/B测试)。
通过简单的数据库字段(last_recall_at, last_recall_clicked_at, last_recall_converted_at)就能构建一个闭环的效果追踪系统,相比使用第三方营销平台,自建PHP系统的优势在于:数据完全可控、与业务系统深度整合(如实时发放优惠券)、成本更低。