返回

根域名实现延迟深度链接与网站共存方案

IOS

根域名延迟深度链接(Deferred Deep Link)实现与网站共存方案

直接说问题吧,现在移动应用安装归因,很多时候需要用到延迟深度链接(Deferred Deep Link),比如通过一个 referral code 来追踪。目前用 Branch.io 挺方便的,但它要求链接必须用子域名,像 link.mycompany.com 这种。 我想直接用根域名 mycompany.com,还能同时放个介绍 App 的简单网页,这可咋整?

下面就来分析分析这问题,并给出几种解决方案。

问题根源:根域名的双重身份

要理解为啥直接在根域名上搞延迟深度链接有困难,得先弄清楚几个概念。

  1. 深度链接 (Deep Link): 一种特殊的 URL,能直接把你带到 App 里的特定页面,而不是仅仅打开 App 主页。
  2. 延迟深度链接 (Deferred Deep Link): 更厉害一点。即使用户没装 App,点了这个链接,会先引导他们去应用商店下载。装好打开后,依然能把你带到链接本想指向的那个页面。
  3. 通用链接/App Links (Universal Links/App Links): iOS (Universal Links) 和 Android (App Links) 各自搞的一套机制,让点击一个普通网页链接时,如果装了对应的 App,就直接打开 App,而不是在浏览器里打开网页。

关键来了:通常,实现延迟深度链接的第三方服务(比如 Branch.io)以及通用链接/App Links,都需要在你的网站根目录放几个特殊文件,像 apple-app-site-association (iOS) 和 assetlinks.json (Android)。这些文件里写着你的 App 的一些信息,告诉操作系统,这个网站和某个 App 是一伙的。

这样一搞,矛盾就出来了:

  • 如果根域名 mycompany.com 完全用来做深度链接,那访问 mycompany.com 就直接跳到 App 了(或者去下载)。你咋放 App 介绍网页?
  • 如果 mycompany.com 放了网页,那访问 mycompany.com/apple-app-site-association 这样的地址,返回的就不是那个特殊文件,而是网页服务器处理后的结果(很可能是 404)。通用链接/App Links 机制就失效了。

解决方案

针对以上问题,可以尝试下几个办法:

1. 服务端路由:让“鱼和熊掌兼得”

这种方法的核心思想是:在你的服务器上做文章,根据请求的路径(path)或 User-Agent 来决定是返回网页内容,还是做深度链接跳转。

原理:

  1. 所有对 mycompany.com 的请求都先到你的服务器。
  2. 服务器检查请求的路径:
    • 如果是 /apple-app-site-association/assetlinks.json,就返回对应的文件内容。
    • 如果是其他路径,比如 //about,就正常返回你的网页内容。
  3. 服务器检查 User-Agent:
    • 如果是移动端(通过user-agent或者特别请求),就直接 302 重定向到应用市场地址。
    • 如果不是移动端就走第二步的路径逻辑判断。

代码示例 (Node.js + Express):

const express = require('express');
const app = express();

// 提供 apple-app-site-association 文件
app.get('/apple-app-site-association', (req, res) => {
  res.setHeader('Content-Type', 'application/json');
  res.sendFile(__dirname + '/apple-app-site-association');
});

// 提供 assetlinks.json 文件
app.get('/assetlinks.json', (req, res) => {
  res.setHeader('Content-Type', 'application/json');
  res.sendFile(__dirname + '/assetlinks.json');
});

//其他所有请求显示网页, 重定向应用商店等
app.get('*', (req, res) => {
  const userAgent = req.headers['user-agent'];
  if (/mobile/i.test(userAgent)) { //简单判断移动设备
    res.redirect('https://yourappstorelink'); //跳转
  }
  else{
    res.sendFile(__dirname + '/public/index.html'); // 显示网页
  }

});

app.listen(3000, () => console.log('Server running on port 3000'));

操作步骤:

  1. apple-app-site-associationassetlinks.json 文件准备好,放到服务器代码的根目录。
  2. 把你的网页文件(比如 index.html)放到一个叫 public 的文件夹里。
  3. 部署这个 Node.js 服务到你的服务器。
  4. 在你的 DNS 设置里,把 mycompany.com 的 A 记录指向你的服务器 IP。

安全建议:
确保下载的文件(apple-app-site-association)符合apple官方标准。
确保重定向的逻辑和时机都正常,以免误导用户或引起安全问题。

进阶技巧:

  • 更精细的 User-Agent 识别:用更完善的库(比如 ua-parser-js)来判断设备类型、操作系统、浏览器等。
  • 根据请求头(headers)做更多判断:比如 Accept-Language 来提供多语言支持。
  • 还可以加上一层反代,通过 Nginx/Apache 来转发和判断,效率更高。

2. 自建延迟深度链接服务(复杂,但更灵活)

如果你不想用 Branch.io 这类第三方服务,可以自己从头搭建一套延迟深度链接系统。但这需要比较强的技术能力。

原理:

  1. 短链接服务: 用一个短链接服务(比如 bit.ly,或者自己搭)把长链接(包含 referral code 等参数)变成短链接。
  2. 链接解析服务: 当用户点击短链接时,这个服务做几件事:
    • 记录 referral code 等信息。
    • 判断用户是否装了 App(通过 Universal Links/App Links,或者尝试调起 App 的自定义 URL Scheme)。
    • 如果没装,引导用户去下载。
    • 把 referral code 等信息存到服务器,或者用某种方式(比如剪贴板)传递给 App。
  3. App 端处理: App 启动时,检查是否有 referral code 等信息,如果有,就做相应的处理(比如给用户奖励)。

代码示例(简略思路,仅供参考):

// 链接解析服务(Node.js + Express)
app.get('/:shortCode', async (req, res) => {
  const shortCode = req.params.shortCode;
  // 1. 从数据库里找到 shortCode 对应的长链接和参数
  const { longUrl, referralCode } = await getLinkData(shortCode);

  // 2. 记录 referralCode 等信息
  await recordReferral(referralCode);

  // 3. 尝试打开 App (这里只是示意,具体实现要看你的 App 怎么配置)
  const appUrl = `myapp://open?referralCode=${referralCode}`;
  res.redirect(appUrl); //如果已经安装App则唤醒

    //4. 不管能不能直接打开 App, 302 重定向,如果上面重定向已经成功则这里不会执行到。
    const userAgent = req.headers['user-agent'];
    if (/mobile/i.test(userAgent)) {
        //跳应用商店
      res.redirect('https://yourappstorelink'); //跳应用商店
    }
    else{
       //跳转网站
      res.redirect('https://mycompany.com/landing'); //
    }
});

操作步骤:

  1. 实现短链接服务。
  2. 实现链接解析服务。
  3. 在 App 里处理延迟深度链接的逻辑。

安全建议

  1. 考虑使用HTTPS
  2. 对于 referralCode 等参数, 务必严格验证其合法性, 并使用加密手段

3. 利用 Firebase Dynamic Links (推荐)

Firebase Dynamic Links 是 Google 提供的一项服务,功能和 Branch.io 类似,但它可以让你用根域名!

原理:

Firebase Dynamic Links 其实也是在背后帮你做了类似“服务端路由”的事情。它提供了一些特殊的 URL 路径(比如 /__/firebase/init.json),用于它的内部处理。同时,它允许你把其他路径映射到你的网页或 App。

操作步骤:
具体怎么操作可以看这儿:

  1. 设置 Firebase 项目:
    创建一个 Firebase 项目并将其连接到你的 iOS 和 Android 应用。

  2. 配置 Dynamic Links:
    在 Firebase 控制台中,启用 Dynamic Links 功能并设置你的域名(可以用根域名)。

  3. 创建动态链接:
    可以通过 Firebase 控制台手动创建动态链接,也可以使用 Firebase SDK 在代码中动态生成。在链接中可以包含 referral code 等参数。

  4. 处理动态链接:
    在你的 React Native + Expo 应用中,使用 Firebase SDK(比如 expo-firebase-dynamic-links)来监听和处理传入的动态链接。

  5. 配置网站托管:
    可以使用 Firebase Hosting 来托管你的 App 介绍网页。Firebase Hosting 会自动处理与 Dynamic Links 的集成。也可以用其他的hosting,手动把/__/firebase/init.json请求正确代理到 Firebase。

代码示例(React Native + Expo):

import * as Linking from 'expo-linking';
import * as FirebaseDynamicLinks from 'expo-firebase-dynamic-links';

// ...

useEffect(() => {
  const handleDynamicLink = link => {
    // 处理深度链接的逻辑,获取参数
    console.log('Got a dynamic link', link);

      //从link.url中取出referralCode之类的参数
  };

    //App前台运行时监听
  Linking.addEventListener('url', ({ url }) => {
        FirebaseDynamicLinks.resolveLink(url).then(handleDynamicLink);
  });

  //App后台或没打开时处理。
  FirebaseDynamicLinks.getInitialLink().then(handleDynamicLink)

  return () => {
      Linking.removeEventListener('url');
  };
}, []);

额外补充

因为用上了 Firebase Dynamic Links, 你还可以结合 Firebase 的其他服务,比如 Analytics,来更全面地追踪用户行为和 App 推广效果。

这几种方法,第一种和第三种相对靠谱,第三种更省事些,建议优先试试。