技术架构与账号准备
实现站外流量复购的核心在于“深度链接”技术。当用户在短信、邮件或Web网页中点击复购链接时,系统能直接唤起App并跳转至指定商品详情页或结算页。本文采用业界成熟的Branch.io SDK进行全链路实现,该方案支持iOS Universal Links和Android App Links,能最大程度保障唤起成功率。
第一步:获取开发密钥
访问 https://dashboard.branch.io 注册账号。登录后进入Dashboard,在左侧导航栏点击Settings -> Account Settings,复制页面顶部的Branch Key(Live Key,测试阶段可用Test Key)。记录该Key,后续配置文件中需要使用。
iOS端深度链接集成
CocoaPods依赖引入
打开终端,进入iOS项目根目录。若未安装CocoaPods,请先执行 sudo gem install cocoapods。初始化并编辑Podfile:
```bash
pod init
```
打开生成的Podfile文件,在target中添加以下依赖:
```ruby
target 'YourApp' do
pod 'Branch-SDK'
end
```
保存后执行安装命令:
```bash
pod install --repo-update
```
安装完成后,使用 .xcworkspace 文件重新打开项目。
Info.plist配置详解
为了支持Universal Links,必须在Info.plist中添加Branch配置。找到 Info.plist 文件,添加以下键值对。请确保将 branch_key 的值替换为你在第一步获取的Key。
```xml
branch_key
live
paste_your_live_key_here
test
paste_your_test_key_here
branch_universal_link_domains
your-app-name.app.link
your-app-name-alternate.app.link
```
注意: branch_universal_link_domains 中的域名必须在Branch Dashboard中配置并关联到你的App Bundle ID。前往Dashboard -> Link Settings -> Domains 查看你的默认域名。
AppDelegate初始化代码
打开 AppDelegate.swift 或 AppDelegate.m,导入头文件并初始化SDK。以下是Swift代码示例:
```swift
import UIKit
import BranchSDK
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 初始化Branch SDK
Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
if error == nil {
// params中包含从链接传递过来的参数
print("Branch params: \(params ?? [:])")
self.handleDeepLinkParams(params: params)
}
}
return true
}
// 处理Universal Links回调 (iOS 9+)
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return Branch.getInstance().application(app, open: url, options: options)
}
// 处理Universal Links回调 (iOS 8及以下)
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return Branch.getInstance().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
}
// 处理续传操作 (iOS 13+)
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
return Branch.getInstance().continue(userActivity)
}
private func handleDeepLinkParams(params: [AnyHashable: Any]?) {
guard let params = params else { return }
// 判断是否为复购链接,通常通过特定参数标识,例如 'type': repurchase'
if let type = params["type"] as? String, type == "repurchase", let productId = params["product_id"] as? String {
// 跳转到商品详情页
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.navigateToProductDetail(productId: productId)
}
}
}
private func navigateToProductDetail(productId: String) {
// 这里实现你的跳转逻辑,例如获取UINavigationController并push ViewController
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let productVC = storyboard.instantiateViewController(withIdentifier: "ProductDetailViewController") as? ProductDetailViewController {
productVC.productId = productId
if let navController = self.window?.rootViewController as? UINavigationController {
navController.pushViewController(productVC, animated: true)
}
}
}
}
```
Android端深度链接集成
Gradle依赖配置
在项目根目录的 build.gradle (Project level) 中添加JitPack仓库:
```groovy
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
```
在App模块的 build.gradle (Module level) 中添加Branch SDK依赖:
```groovy
dependencies {
implementation 'io.branch.sdk.android:library:5.4.0'
}
```
AndroidManifest.xml配置

打开 AndroidManifest.xml,添加 BranchApp 类(如果没有则创建一个继承自Application的类)并在 标签中声明。同时,必须添加用于接收App Links的 。请将 your_app_name 替换为你的实际Link域名前缀。
```xml
```
Application与Activity代码实现
创建自定义的Application类 MyApplication.java:
```java
package com.example.yourapp;
import android.app.Application;
import io.branch.referral.Branch;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 初始化Branch
Branch.getAutoInstance(this);
}
}
```
在 MainActivity.java 中处理链接传入的数据:
```java
package com.example.yourapp;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import io.branch.referral.Branch;
import io.branch.referral.BranchError;
import io.branch.referral.util.LinkProperties;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
// 初始化Session并监听链接点击
Branch.sessionBuilder(this).withCallback(new Branch.BranchReferralInitListener() {
@Override
public void onInitFinished(JSONObject referringParams, BranchError error) {
if (error == null) {
try {
// 解析参数
String type = referringParams.optString("type", "");
String productId = referringParams.optString("product_id", "");
if ("repurchase".equals(type) && !productId.isEmpty()) {
// 执行跳转逻辑
navigateToProductPage(productId);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).withData(this.getIntent().getData()).init();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
this.setIntent(intent);
// 必须重新调用init以处理新的Intent
Branch.sessionBuilder(this).withCallback(new Branch.BranchReferralInitListener() {
@Override
public void onInitFinished(JSONObject referringParams, BranchError error) {
if (error == null) {
try {
String type = referringParams.optString("type", "");
String productId = referringParams.optString("product_id", "");
if ("repurchase".equals(type) && !productId.isEmpty()) {
navigateToProductPage(productId);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).reInit();
}
private void navigateToProductPage(String productId) {
// 实际项目中这里跳转到具体的Fragment或Activity
// 示例代码:
// Intent intent = new Intent(this, ProductDetailActivity.class);
// intent.putExtra("product_id", productId);
// startActivity(intent);
}
}
```
生成复购链接的代码实现
为了实现站外流量复购,通常需要在服务端或App内生成包含特定参数的Branch链接。以下是在客户端生成复购链接的通用逻辑。该链接将用于邮件营销、短信推送或Web落地页。
假设场景:用户购买过商品ID为 12345 的商品,现在发送复购提醒。
```java
// Android端生成链接示例
public void generateRepurchaseLink() {
BranchUniversalObject buo = new BranchUniversalObject()
.setCanonicalIdentifier("item/12345")
.setTitle("复购专享商品")
.setContentDescription("您购买过的商品正在促销,点击立即复购")
.setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC);
LinkProperties lp = new LinkProperties()
.setChannel("email") // 设置渠道:email, sms, wechat等
.setFeature("repurchase_reminder")
.addControlParameter("$desktop_url", "https://www.yourwebsite.com/product/12345")
.addControlParameter("$ios_url", "https://apps.apple.com/app/id123456789") // 如果未安装App跳转AppStore
.addControlParameter("$android_url", "https://play.google.com/store/apps/details?id=com.example.yourapp");
// 添加自定义参数,用于客户端识别
buo.setContentMetadata(new ContentMetadata()
.addCustomMetadata("type", "repurchase")
.addCustomMetadata("product_id", "12345"));
buo.generateShortUrl(this, lp, new Branch.BranchLinkCreateListener() {
@Override
public void onLinkCreate(String url, BranchError error) {
if (error == null) {
System.out.println("Generated Repurchase Link: " + url);
// 将此url发送到服务端或直接用于分享
} else {
System.out.println("Link generation failed: " + error.getMessage());
}
}
});
}
```
```swift对应iOS端生成链接示例
func generateRepurchaseLink() {
let buo: BranchUniversalObject = BranchUniversalObject(canonicalIdentifier: "item/12345")
buo.title = "复购专享商品"
buo.contentDescription = "您购买过的商品正在促销,点击立即复购"
buo.contentMetadata.customMetadata["type"] = "repurchase"
buo.contentMetadata.customMetadata["product_id"] = "12345"
let lp: LinkProperties = LinkProperties()
lp.channel = "email"
lp.feature = "repurchase_reminder"
lp.addControlParam("$desktop_url", withValue: "https://www.yourwebsite.com/product/12345")
lp.addControlParam("$ios_url", withValue: "https://apps.apple.com/app/id123456789")
buo.generateShortUrl(lp, { (url, error) in
if error == nil {
print("Generated Repurchase Link: \(url ?? ""))
// 发送url到服务器
}
})
}
```
客户端路由与页面跳转逻辑
当用户点击生成的链接,App被唤起后,handleDeepLinkParams (iOS) 或 onInitFinished (Android) 将捕获参数。核心逻辑在于解析 type 和 product_id。
关键步骤:
- 参数校验: 确保传入的
product_id 格式正确且不为空。
- 登录态检查: 复购通常需要用户已登录。如果检测到未登录,应先跳转登录页,并将
product_id 作为登录成功后的回调参数保存。
- 路由跳转: 使用路由库(如Android的ARouter,iOS的JLRoutes)或直接显式Intent跳转。
以下是一个简单的登录态检查与跳转逻辑补充(伪代码):
```java
private void navigateToProductPage(String productId) {
if (!UserManager.isLoggedIn()) {
// 保存目标页面信息
LoginHelper.setPendingAction("product_detail", productId);
// 跳转登录
startActivity(new Intent(this, LoginActivity.class));
return;
}
// 已登录,直接跳转
Intent intent = new Intent(this, ProductDetailActivity.class);
intent.putExtra("product_id", productId);
// 添加FLAG_CLEAR_TOP,避免返回栈中堆积过多页面
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
```
全链路测试验证
完成代码集成后,必须进行真机测试以验证深度链接是否生效。
1. iOS测试步骤:
- 确保手机已安装你的App(测试版或Debug版均可)。
- 确保手机未连接Xcode调试(为了测试Universal Links,必须从桌面图标启动App,或者直接点击链接)。
- 将生成的短链接发送到手机备忘录或邮件中。
- 长按链接,选择“在‘YourApp’中打开”。如果直接点击,系统会自动判断是否支持Universal Links。
- 观察App是否启动并直接跳转到了
ProductDetailViewController。
2. Android测试步骤:
- 安装App到真机。
- 确保App已安装,且Android版本支持App Links。
- 点击生成的短链接。
- 系统弹窗应显示“用YourApp打开此链接”或直接打开App。
- 检查Logcat日志,搜索 "Branch" 关键字,确认参数
product_id 是否正确输出。
3. 强制跳转测试:
为了测试未安装App的情况,可以直接在浏览器中打开链接,或者修改链接参数 $android_url 和 $ios_url 指向一个测试网页,确认流程会跳转到Web页面或应用商店。