みてねでは以下の要件を満たすために Short Links API を利用していました
- Deep Link
- URL タップでアプリの指定した画面に飛ばす
- Deferred Deep Link
- アプリ未インストール時は App Store / Google Play Store に遷移してユーザーがインストールしたあとの初回アプリ起動時に指定したDeep Link の画面に飛ばす
- URL をできるだけ短く
- 文字数制限がある SMS 内のリンクとして利用しているため
- 動的な URL を生成する
大体同じことができる印象ですが強いて言えばリンクの有効期限が異なっています
項目 | Firebase DynamicLinks Short Links API | AppsFlyer OneLinks API |
---|---|---|
仕様 | https://firebase.google.com/docs/reference/dynamic-links/link-shortener?hl=ja | https://dev.appsflyer.com/hc/reference/create-onelink-attribution-link |
APIエンドポイント | https://firebasedynamiclinks.googleapis.com/v1/shortLinks |
https://api.appsflyer.com/v1/shortlink/#{onelink-id} (onelink-idはAppsFlyerの管理画面で作成したテンプレートのID) |
認証方法 | URLパラメーターで key=YOUR_API_KEY を指定 |
HTTPヘッダー authentication: #{dev_key} を指定 |
ベースURL | #{your_subdomain}.page.link |
#{your_subdomain}.onelink.me |
リンク有効期限 | 明示的な期限指定不可。1年以上有効だったという話もあり半永久的に有効かも | デフォルトおよび最大は31日。時/分/日で指定可能 |
SDK統合 | Firebase SDK 必須 | AppsFlyer SDK 必須 |
- AppsFlyer の管理画面で OneLink テンプレートを作成
- OneLink テンプレート作成後に表示されるテンプレートIDをこれ以降の server 側の実装で利用します
server(ruby)
OneLink 作成
require 'uri'
require 'net/http'
template_id = 'AppsFlyerの管理画面で作成したテンプレートのID'
url = URI("https://onelink.appsflyer.com/shortlink/v1/#{template_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request['accept'] = 'application/json'
request['content-type'] = 'application/json'
request['authorization'] = 'AppsFlyer OneLink API Token を指定'
request.body = {
data: {
deep_link_value: 'https://feedme.ca/deeplink',
deep_link_sub1: 10,
pid: 'my_media_source_SMS'
af_android_url: 'https://feedme.ca/buybananas',
af_ios_url: 'https://feedme.ca/buybananas',
is_retargeting: true,
af_adset: 'my_adset',
af_channel: 'my_channel',
af_dp: 'afbasicapp://mainactivity',
c: 'my_campaign',
}
}.to_json
response = http.request(request)
puts response.read_body
iOS
class AppDelegate: UIResponder, UIApplicationDelegate,
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
AppsFlyerLib.shared().deepLinkDelegate = self
}
}
extension AppDelegate: DeepLinkDelegate {
func didResolveDeepLink(_ result: DeepLinkResult) {
switch result.status {
case .notFound:
print("Deep link not found")
case .found:
guard let deepLinkStr = result.deepLink?.toString() else { return }
print("DeepLink data is: \(deepLinkStr)")
if( result.deepLink?.isDeferred == true) {
print("This is a deferred deep link")
} else {
print("This is a direct deep link")
}
case .failure:
print("Error \(result.error?.localizedDescription ?? "")")
}
}
}
Android
-
AndroidManifest.xml
に OneLink のドメイン(xxx.onelink.me)の intent-filter を追加
activity
android:name=".SampleActivity"
android:theme="@style/xxxx" />
intent-filter android:autoVerify="true">
action android:name="android.intent.action.VIEW" />
category android:name="android.intent.category.DEFAULT" />
category android:name="android.intent.category.BROWSABLE" />
data
android:host="${one_link_domain}"
android:scheme="https" />
intent-filter>
- Unified Deep Linking タップした時の処理を実装
class AppsflyerBasicApp : Application {
override fun onCreate() {
val conversionListener = object : AppsFlyerConversionListener {
override fun onConversionDataSuccess(data: MutableMapString, Any>?) {}
override fun onConversionDataFail(error: String?) {}
override fun onAppOpenAttribution(data: MutableMapString, String>?) {}
override fun onAttributionFailure(error: String?) {}
}
AppsFlyerLib.getInstance().init(AF_DEV_KEY, conversionListener, this).apply {
subscribeForDeepLink {
val deepLinkValue = it.deepLink.deepLinkValue ?: return@subscribeForDeepLink
if (it.deepLink.isDeferred()) {
Log.d(LOG_TAG, "This is a deferred deep link")
} else {
Log.d(LOG_TAG, "This is a direct deep link")
}
}
start(this@AppsflyerBasicApp)
}
}
}
- iOS / Android アプリをテストするにはテストデバイスとしてAppsFlyerの管理画面に登録する必要があります
-
みてねでは、Firebase DynamicLinks で実現していた機能(Deep Link、Deferred Deep Link、短縮URLの生成など)を AppsFlyer OneLink API で代替できました
-
移行にあたっては、AppsFlyer管理画面でのテンプレート作成と、OneLink生成のAPI実装(サーバー)、アプリ側の Unified Deep Linking 対応(iOS/Android) が必要でした。
-
もし Firebase DynamicLinks の廃止で困っている方がいたら参考にしてもらえると嬉しいです。
Views: 0