如何使用 MixPanel 配置 In App Notification?
结论
showNotification() 只会展示当前用户符合投放条件,并且 Mixpanel SDK 已经获取到的 In App Notification。它不会创建通知,也不能强制下发通知。
要在 Payment 页面显示 promo code,需要满足以下条件:
- Mixpanel 后台已经创建并启用了 In App Notification campaign。
- Campaign 关联的 Mixpanel project/token 与应用当前使用的一致。
- 当前用户符合 campaign 设置的受众、时间和触发条件。
- 应用已经调用
identify,且distinct_id与 Mixpanel 后台的目标用户一致。 - SDK 已经获取到 notification 数据。
- 页面显示完成后,在主线程调用展示方法。
因此,通常应该在 viewDidAppear(_:) 中调用,而不是在 viewWillAppear(_:) 中调用。
推荐调用方式
先确认 Mixpanel 实例不是 nil,完成用户识别,再等 Payment 页面显示后调用:
import Mixpanel
final class PaymentViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let mixpanel = Mixpanel.sharedInstance()
DispatchQueue.main.async {
mixpanel.showNotification()
}
}
}
Mixpanel iOS SDK 版本不同,单例 API 也可能不同。如果项目采用较新的初始化方式,应使用应用初始化时保存的同一个实例,不要重新创建。例如:
final class PaymentViewController: UIViewController {
private let mixpanel: MixpanelInstance
init(mixpanel: MixpanelInstance) {
self.mixpanel = mixpanel
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
DispatchQueue.main.async {
self.mixpanel.showNotification()
}
}
}
排查问题时,不要依赖下面这种写法:
mixpanel?.showNotification()
如果 mixpanel 为 nil,可选链会直接跳过调用,也不会报错,表面上很像 Mixpanel 没有返回通知。调试时应明确检查实例:
guard let mixpanel = mixpanel else {
assertionFailure("Mixpanel instance is nil")
return
}
mixpanel.showNotification()
确认用户身份
如果 campaign 按用户属性、分群或指定测试用户投放,需要先识别用户,再尝试展示:
let mixpanel = Mixpanel.sharedInstance()
mixpanel.identify(user.id)
mixpanel.people.set([
"$email": user.email,
"plan": user.plan
])
这里要重点检查 distinct_id。如果应用使用的 distinct_id 与 Mixpanel 后台用户资料中的 ID 不一致,即使后台配置了目标用户,SDK 也不会判断当前设备符合投放条件。
登录状态变化时,还要注意调用顺序:
mixpanel.identify(user.id)
// 更新用户属性
// 等待 SDK 获取到对应用户可用的 campaign
// 再进入或展示 Payment 页面
不要等通知展示后才调用 identify。
检查 Campaign 配置
在 Mixpanel 后台逐项检查:
- Campaign 已经发布,不是草稿,也没有暂停。
- Campaign 使用的 project token 与应用初始化 Mixpanel 时的 token 完全一致。
- 当前测试用户符合受众条件。
- Campaign 的开始时间、结束时间和用户时区没有排除测试用户。
- 用户没有因为展示次数、频率限制或已经完成 campaign 而失去资格。
- 如果 campaign 由事件触发,应用确实上报了对应事件,事件名的大小写也完全一致。
- 测试设备没有被项目的开发、测试或过滤规则排除。
如果想在用户进入 Payment 页面时触发,可以先记录一个明确的事件:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let mixpanel = Mixpanel.sharedInstance()
mixpanel.track("Payment Page Viewed", properties: [
"source": "checkout"
])
DispatchQueue.main.async {
mixpanel.showNotification()
}
}
是否需要显式调用 showNotification(),要看项目使用的 Mixpanel SDK 版本和 campaign 的触发方式。有些旧版本会在事件匹配后自动尝试展示,有些集成方式则需要手动调用。应以项目实际安装版本对应的 SDK 文档为准,不要混用不同版本的示例。
为什么建议使用 viewDidAppear
执行 viewWillAppear(_:) 时,Payment 页面可能还没有进入完整的视图层级。In App Notification 通常需要找到当前可见的 UIViewController,再以模态方式展示。调用过早可能遇到以下情况:
- 页面还没有可用的 presentation context;
- 导航转场仍在进行;
- 另一个控制器正在展示;
- 系统出现 “view is not in the window hierarchy” 一类警告;
- 通知已经匹配,但展示失败。
改在 viewDidAppear(_:) 中调用,可以减少这类问题:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard presentedViewController == nil else {
return
}
Mixpanel.sharedInstance().showNotification()
}
还要避免页面反复出现时重复调用。可以增加一次性保护:
private var hasRequestedNotification = false
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard !hasRequestedNotification else {
return
}
hasRequestedNotification = true
Mixpanel.sharedInstance().showNotification()
}
排查顺序
如果通知仍未显示,可以按下面的顺序排查:
- 确认 Mixpanel 实例不是
nil。 - 打印当前
distinct_id,并与后台测试用户对照。 - 确认 project token 和运行环境正确。
- 暂时将 campaign 缩小到只投放给一个明确的测试用户。
- 先去掉复杂的分群、频率和时间条件,验证最简单的投放是否正常。
- 确认触发事件已经出现在 Mixpanel 中。
- 将调用移到
viewDidAppear(_:),并确保它在主线程执行。 - 查看 Xcode 控制台中的 Mixpanel 网络请求和视图展示错误。
- 检查当前 SDK 版本是否仍支持该 In App Notification API。
Mixpanel 的 In App Notification/Messages 功能及相关 iOS API 在不同历史版本中变化较大,部分旧功能可能已经停止提供。如果后台已经没有对应的 campaign 创建入口,或者当前 SDK 中不存在 showNotification(),就不能继续照搬旧文档。此时应改用 Mixpanel 当前提供的消息能力,或者由应用根据 Remote Config、实验分组或后端接口自行展示 promo code。
备注:内容仅供参考。
