Deep Link (App Wake‑up) Architecture and Implementation at Zhuanzhuan
This article explains how Zhuanzhuan implements deep‑link (app wake‑up) across various scenarios, covering functional and technical architectures, common methods such as URL Scheme, Universal Link, WeChat wake‑up, and in‑app calls, with best‑practice code snippets and deployment tips.
Wake‑up Function Architecture
Zhuanzhuan is the core product of our company; guiding users to the Zhuanzhuan App is crucial for growth and retention. The typical approach is to place a web‑based landing page at traffic entry points and use it to launch the app (hereafter referred to as “wake‑up”). This article focuses on how Zhuanzhuan completes the entire wake‑up process in different scenarios.
We first show a GIF illustrating a simple wake‑up: clicking the button in Safari prompts the system to open the app, and the app is launched.
If the app is not installed, the user is redirected to a download page.
Thus, wake‑up generally includes three functions: Launch App , Download App , and Auto‑download after launch failure .
Wake‑up also needs to open a specific page inside the app (e.g., the order page) to avoid losing conversion.
The overall functional flow is illustrated in the following diagram:
Wake‑up Technical Architecture
The technology used for wake‑up is generally called Deep Link. Different platforms implement it differently, with the main standards being:
URL Scheme (cross‑platform)
Universal Link (iOS‑specific)
App Links and derived Chrome Intents (Android‑specific)
In addition to these international standards, domestic environments such as WeChat, Weibo, and UC Browser require special handling. Common wake‑up methods for these platforms include:
Universal Link (partially usable, often blocked by domestic apps)
WeChat API launchApplication and getInstallState (requires whitelist, high difficulty)
WeChat open tag <wx-open-launch-app> (recommended, requires review)
Redirect to YingYongBao and launch via its App Link (Android, WeChat environment)
Show a modal prompting the user to click the top‑right button to open in the browser
The technical architecture is summarized in the following diagram:
Common Wake‑up Methods Details
We will discuss four main scenarios: URL Scheme , Universal Link , WeChat wake‑up , and Our own App launching other Apps .
URL Scheme
A URL Scheme is the protocol part of a URL, e.g., https://m.zhuanzhuan.com where https is the scheme.
Consider the address zhuanzhuan://jump/core/myBuyList/jump?tab=0 . If the system has registered the scheme zhuanzhuan:// to the Zhuanzhuan App, the system will open the link with the app, which then parses the path and query to perform the corresponding action.
Registration of the scheme:
Android – add an intent‑filter in the manifest .
iOS – add a URL type in info.plist .
Calling the Scheme
The scheme can be invoked via location.href , an iframe , or an a tag. The three methods are equivalent; choose another if one fails.
Best practice after extensive testing:
In iOS QQ environment, use an a tag.
Otherwise, use location.href .
If you want to avoid navigation on error, use an iframe (watch for device compatibility).
Example code:
// SCHEMA_PATH is the URL Scheme address
// location.href method
window.top.location.href = SCHEMA_PATH;
// a tag method
const a = document.createElement("a");
a.setAttribute("href", SCHEMA_PATH);
a.click();
// iframe method
iframe = document.createElement('iframe');
iframe.frameBorder = '0';
iframe.style.cssText = 'display:none;border:0;width:0;height:0;';
document.body.append(iframe);
iframe.src = SCHEMA_PATH;Auto‑download on Failure
Since a Scheme call does not provide success feedback, a common approach is to start a timer (e.g., 2.5 s) that triggers a download, and listen for the visibilitychange event; if the page becomes hidden, the app was launched and the timer is cleared.
Implementation:
// Execute download after n seconds
const timer = setTimeout(() => {
this.__download(options);
}, options.delay);
// If page hides, cancel the timer
const visibilitychange = function() {
const tag = document.hidden || document.webkitHidden;
tag && clearTimeout(timer);
};
document.addEventListener("visibilitychange", visibilitychange, false);
document.addEventListener("webkitvisibilitychange", visibilitychange, false);
window.addEventListener("pagehide", function() {
clearTimeout(timer);
}, false);The value of n varies by device; testing shows 2500‑3000 ms works well.
iOS Specific Issues
When the user confirms the system alert, the JavaScript continues to run. If the elapsed time between the click and the return to Safari exceeds n , the download logic may still execute, causing both launch and download to run.
Animated GIFs illustrate the timing difference.
Universal Link
Universal Link, introduced in iOS 9, allows direct app launch via an https link. If the app is not installed, the link simply opens the web page, eliminating the need for explicit success detection and avoiding the confirmation prompt.
Example: navigating to https://mjump.zhuanzhuan.com/zhuanzhuan/index.html via location.href launches the app.
Configuration steps:
Configure an Associated Domain for the app (e.g., mjump.zhuanzhuan.com ).
During app installation, iOS fetches the apple-app-site-association file from the domain or its .well-known path.
When a cross‑origin navigation occurs (e.g., from m.zhuanzhuan.com to mjump.zhuanzhuan.com ), iOS matches the requested path against the paths defined in the association file; a match launches the app, otherwise the web page loads.
{
"applinks": {
"apps": [],
"details": [
{
"appID": "ECVV5G85CD.com.wuba.zhuanzhuan",
"paths": ["zhuanzhuan/*", "/qq_conn/1104903352/*"]
},
{
"appID": "ECVV5G85CD.com.zhuanzhuan.yige",
"paths": ["yige/*"]
},
{
"appID": "75BF75R4NH.com.wuba.*",
"paths": ["*"]
}
]
}
}WeChat Wake‑up
WeChat 7.0.5 opened Universal Link support on iOS, allowing wake‑up without extra prompts. On Android, we can route through YingYongBao (App Store) and use its App Link to open a specific page.
WeChat API – launchApplication
Early versions provided launchApplication and getInstallState . The former launches an app; the latter checks installation status on Android. These APIs require a whitelist, which is now hard to obtain, so the open tag <wx-open-launch-app> is recommended.
Configuration example:
wx.config({
debug: false,
appId: conf.appId,
timestamp: conf.timestamp,
nonceStr: conf.noncestr,
signature: conf.signature,
beta: true,
jsApiList: ['launchApplication', 'getInstallState'],
openTagList: ['wx-open-launch-app']
});Calling the APIs:
/**
* @description Launch third‑party app via WeChat
*/
launchApplication(options) {
return WeixinJSBridge.invoke('launchApplication', options, res => {
console.log(res);
});
}
/**
* @description Check if Android app is installed (iOS unsupported)
*/
getInstallState(options) {
return WeixinJSBridge.invoke('getInstallState', options, res => {
console.log(res);
});
}WeChat Open Tag – wx-open-launch-app
The open tag is the officially recommended way, but it requires a public account and an Open Platform account bound together; our company’s accounts differ, so we could not use it.
Our Own App Launching Other Apps
Our app can invoke system APIs such as openURL to launch other apps (e.g., Alipay, WeChat). The key is to load the target app’s SDK dynamically and ensure it is initialized before calling.
Source Code
The wake‑up logic is open‑sourced for reference. Repository: https://github.com/zhuanzhuanfe/call-app
Upcoming Articles
We will continue to publish articles on hybrid, micro‑frontend, Umi, and other foundational architecture and middle‑platform practices.
End‑of‑Article Giveaway
Share this article and comment; the 30th commenter will receive a physical copy of "JavaScript: The Good Parts (4th Edition)".
Reference
Official Documentation: https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_H5_Launch_APP.html
转转QA
In the era of knowledge sharing, discover 转转QA from a new perspective.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.