3月のDACH製品ローンチで18,000枚のフライヤーを印刷しました。裏面に1つの短縮リンク、人々を誘導したい3つの地域のランディングページ:ドイツ語の訪問者には /de、フランス語の小さなスライスには /fr、それ以外の全員には /en。マーケティングリードが明白な質問をしました:3枚のフライヤーを印刷するのか、1枚か?
1枚を印刷します。リンクがルーティングを行います。
「スマートリンク」とは、転送先がリンク作成時ではなくリダイレクト時に計算される単一の短縮URLです。スラグは1つあります。考えられる転送先はいくつかあります。決定はプレーンな 302 を発行するハンドラーと同じ場所で起こります - 別のサービスを呼び出す必要もなく、ランディングページにJSシムもなく、追加のホップもありません。この記事は、それが実際にどのように見えるか、Elidoがルーティングに使用する6つのディメンション、そして代わりに別のツールを使うべきケースについてです。
スマートリンクでないもの3つ#
人々はスマートリンクを3つの異なる以前の経験から使おうとします。それぞれでトレードオフが異なります。
プレーンなリダイレクト。 1つのスラグ、1つの転送先、ゼロのロジック。リダイレクトハンドラーはキャッシュルックアップを行い、302を書きます。レイテンシーでは勝てません。条件付きにもできません。これがフロアです - 凝ったものはすべて何かのコストがかかります。
エッジのスマートリンク。 1つのスラグ、いくつかの考えられる転送先、キャッシュルックアップとレスポンスの間に挿入された小さなルール評価ステップ。ルールはキャッシュルックアップと同じプロセスに存在するため、コストはサブミリ秒です(Elidoの場合はp50が0.3ms / p95が1ms)。訪問者は1つのHTTPラウンドトリップを見ます。ブラウザキャッシュは汚染されません。なぜならRFC 7234 §4.2.2によると302レスポンスはデフォルトではキャッシュできないからです - これは重要な事実です。リクエストごとのルーティングは、すべてのリクエストが独自の転送先を選べる場合にのみ意味があります。
ランディングページでのJavaScript A/Bルーター。 ニュートラルなHTMLページがレンダリングされ、JSが navigator.userAgent またはジオIPサービスを検査し、その後 window.location = '/foo' を行います。これは3つの中で最悪のオプションです。訪問者はHTMLのレンダリング、次にリダイレクト、次に実際のページを見ます - 少なくとも1つの余分なラウンドトリップ、ジオルックアップがサードパーティの場合はしばしば2つ。SEOのインデックスはクローラーがニュートラルなページを見るため混乱します。Cookie をブロックするブラウザとプライバシー拡張機能がJS部分を壊します。AppleのIntelligent Tracking Prevention 2.3のリリースノートは正確にこのパターンを指摘しています:document referrerを介したクライアントサイドのトラッキングリンクはスロットリングされ、軽減策にはサーバーサイドの関与が必要です。今日JSでルーティングしているなら、すでにその請求書を払っています。
ルーティング決定を置く正しい場所は、すでにリダイレクトを発行しているのと同じホップです。それがエッジスマートリンクがすることです。
なぜエッジに存在するのか - レイテンシーバジェット#
Elidoのリダイレクトティアには厳しいレイテンシーバジェットがあります:キャッシュヒット時のp50は5ms、p95は15ms(TLSハンドシェイクを除く)。その数値は野心的なものではありません - それを超えるものはすべて取り出されます。ホットパスでの同期SQL、リクエストごとの正規表現コンパイル、クリックイベントでのブロッキングI/O:すべて削除され、コールドパスのワーカーに移動されました。
そのバジェットが存在する2つの理由:
- モバイルネットワークは独自の税を追加します。 Appleの「ネットワークレイテンシーの削減」ガイドは、セルラーネットワークの遅延がリダイレクトチェーン全体でどのように複合するかを説明しています。追加ホップはそれぞれ、訪問者のネットワークがすでに膨らませたRTTを加算します。私たちが追加するホップが少ないほど、ネットワークが訪問者を罰する機会が減ります。
- エッジの近接性が本当のレバーです。 CloudflareのエッジサイドルーティングのPrimerも同様に述べています:最も安い決定は、訪問者に最も近いPOPで、レスポンスライターと同じプロセスで行われるものです。エッジルーティングをすることで私たちはユニークではありません。ユニークなのは、それを別のWorkers / Lambda@Edgeファンクションをデプロイするよう頼む代わりに、URLショートナーにバンドルしたことです。
ルール評価をダウンストリームサービス - たとえば仮想の「rules-api」をHTTP経由で到達可能なもの - に委ねた場合、すべてのリクエストにサームリージョンのラウンドトリップが追加されます。リージョン内では最低約5ms(同一リージョンのプライベートネットワーク経由のホップ)、そしてクロスリージョンのトラフィックではテールが非常に速く悪化します。15ms p95はラウンドトリップを生き残れません。そのためスマートリンクのルールはインラインで、エッジバイナリ内で、リンクがキャッシュにロードされたときに構築されたコンパイル済みマッチャーに対して評価されます。ルールエンジン全体は約400行のGoです。
この密結合が、リアルタイムのルール編集が可能な理由でもあります:ルールの変更はすべてのエッジPOPが購読するインメモリキャッシュのpub/subチャンネル(link:invalidate)経由で伝播します。L1 LRUはパブリッシュから1秒以内にエビクトし、次のリクエストがL2から再取得し、新しいルールが有効になります。詳細は後述します。
6つのルーティングディメンション#
Elidoのスマートリンクは6つのものにマッチします。それぞれがエッジがリクエストごとにアクセスできる特定の入力にマッピングされます。
国。 geoip経由で訪問者のIPから導出された2文字のISO 3166-1 alpha-2。地域のストアフロントを持ち、国ごとのコンバージョンのリフトがルーティングの複雑さに見合う場合に有用です。ここでの典型的な落とし穴は旅行者です - スペインで休暇中のドイツ人は、国だけでルーティングするとスペインの転送先に到達します。地理的な場所より言語の好みが重要な場合は、代わりに languages でルーティングします。完全なgeoipフローについてはアナリティクスプライバシーの記事で説明しています - IPは保存前に切り捨てられるため、GDPR側はクリーンに保たれます。
デバイス。 リクエスト時にUser-Agent文字列から解析された mobile、tablet、desktop。マーケターがこれを使うユースケース:iOSではApp Storeへ、AndroidではPlay Storeへ、デスクトップではマーケティングページへ行くアプリインストールバナー。注意すべきこと:iPadOSがデフォルトでデスクトップSafariのUAを表示し始めてから、iPad上のUser-Agent文字列は動くターゲットになっており、タブレット検出はそれに対応していますが、すべてのブラウザバージョンで100%ではありません。タブレットとデスクトップのトラフィックの違いが金銭的に重要な場合は、転送先をインストルメントして確認してください。
OS。 ios、android、macos、windows、linux。デバイスと同じUser-Agentソース、より狭いパーティション。ディープリンクのケース:iOS訪問者をアプリがインターセプトしてApp Storeにフォールバックするユニバーサルリンクにルーティングする。Androidにはリファラーデータを保持したままPlay Storeにルーティングする。これがApple App Site Association統合を構築した理由です。
言語。 訪問者の Accept-Language ヘッダーからのプライマリ言語タグ。de、fr、pt のようなISO 639-1コード。落とし穴:Accept-Language はブラウザの好みで、IPジオとしばしば一致しません。ベルリンのフランス系移民は country: DE, languages: ["fr", "en"] を得ます - /fr にしたい場合は言語でルーティングします。ローカライズされた価格のA/Bテストをしているためドイツのストアフロントにしたい場合は国でルーティングします。それに応じてルールを並べます。
時間帯と曜日。 任意のIANAタイムゾーンの HH:MM ウィンドウに days_of_week ビットマップを加えたもの。時間制限のあるオファー - 月〜金の17:00 Europe/Berlinに有効になり、その時間外は通常ページにフォールバックする「ハッピーアワー」ランディングページ - に自然にフィットします。time_start / time_end ウィンドウはラップアラウンドをサポートします(22:00 → 02:00)。明白に聞こえますが、それを処理しなかったプロトタイプからルールエンジンを移植するときに引っかかりました。完全なスキーマはスマートリンクガイドにあります。
リファラーホスト。 Referer ヘッダーのホスト名部分、正規化されたもの。パートナーアウェアな転送先に有用です:partner.example から来た訪問者はコブランドのランディングページを得て、それ以外の全員はデフォルトを得ます。以前よりも有用でなくなっています - モダンブラウザは、参照ページが Referrer-Policy: no-referrer を設定している場合や、ポリシーが許可しない方法でナビゲーションがHTTPSコンテキストを跨ぐ場合に積極的に Referer を削除します。リファラールールをソフトなシグナルとして扱い、認証として絶対に扱わないでください。
以上が全部です。6つのディメンションは3年間の顧客との会話で見てきたマーケティングルーティングの決定をカバーします。意図的に省いたものは、ユーザーアイデンティティ(リダイレクト時には知りません)、任意のHTTPヘッダー(コスト対効果が、要求した少数のチームには見合いません)、ランダム化されたスプリット(代わりに別の機能であるバリアントローテーションを使用します)です。
ファーストマッチセマンティクス:フォールバックは常に必須#
ルールは配列です。エッジはそれらを順番に歩きます。match ブロックが完全に満たされた最初のルールが勝ち、その destination_url がリダイレクトターゲットになります。リンクのトップレベルの destination_url が無条件のフォールバックです。フォールバックなしでスマートリンクを作成することを拒否します - スマートリンクは設計上、404を生成しません。
最小限の実行可能な形状:
{
"destination_url": "https://acme.example/en",
"targeting_rules": [
{
"match": { "countries": ["DE", "AT", "CH"] },
"destination_url": "https://acme.example/de"
},
{
"match": { "languages": ["fr"] },
"destination_url": "https://acme.example/fr"
}
]
}
DACH訪問者はルール1が最初にマッチするため /de に到達します。ベルリンのフランス系移民は country=DE を持つため、ルール2が機会を得る前にルール1がマッチするため、同じく /de に到達します。フランス系移民を /fr にしたい場合は、言語ルールが最初にチェックされるようにルールを入れ替えます。ダッシュボードの順序が評価する順序です。
これが意味する2つのことを明示的に述べておく価値があります:
- より広いルールは最後に来る。
match条件のないルールはすべてにマッチします。最初にある場合、その下のルールは発火しません。ダッシュボードはこれに対して検証して警告しますが、APIは行いません。スクリプトで構築されたルールには健全性チェックが必要です。 - 相互排他はあなたの責任です。 2つのルールが1人の訪問者に両方マッチする場合、最初のものが黙って勝ちます。エラーもフラグもメトリクスもありません。2つのルールが重複しているとして検出可能な場合、リンクロード時に警告を出すことを検討しました。それは次のマイナーリリースのロードマップにあります。今は:ルールを上から下に読んで順序を信頼してください。
コスト:キャッシュ無効化の伝播#
すべてのルーティング決定には伝播ウィンドウがあります。ダッシュボードで編集されたスマートリンクのルールは、ハッピーパスで約1秒以内にすべての3つのElido POPのL1キャッシュを通じて伝播します。おおよそ、というのは:
- 各POPのL1 LRUはルールを持つリンクを60秒のTTLで保持します(キャッシュアーキテクチャはこちらに文書化されています)。TTLは上限です - 無効化パブリッシュなしでも、古いエントリは1分以内に消えます。
- 無効化パブリッシュはインメモリキャッシュのpub/sub経由です。EUと米国東部のPOPはキャッシュクラスターを共有し、アジア太平洋は独自のものを持ちます。クロスリージョンの伝播は本質的にキャッシュレプリケーションレイテンシーに加えてサブスクライバーのpub/sub処理であり、先四半期のメトリクスでp99が1秒以内でした。
- キャッシュサブスクリプションを失ったPOPは60秒のTTLにフォールバックします。サブスクリプションの喪失にアラートを出します。オンコールはWALが起動する前に5分間のバッファされたクリックがあります。
翻訳:60秒の古いルーティングが問題ないマーケティングフローでは、これについて考える必要はありません。古くなることが重要なフロー - 法的免責事項のローテーション、間違った転送先が間違った通貨を請求する課金コホートスプリット - では、まず status=disabled にして、1分後に再有効化し、新しいルールを公開します。CIパイプラインがダウンストリームのスイッチを切り替える前に伝播の完了をポーリングできるよう、GET /v1/links/{id}/status エンドポイントを追加しました。
スマートリンクを使うべきでない場合#
適切なツールがスマートリンクでない3つのケース。
転送先のサーバーサイドレンダリングの方が優れている。 バリアントをHTMLレスポンスに注入する必要がある場合 - たとえば訪問者の認証状態に依存する価格のローカライゼーション、またはCMSからコホート固有のヒーローを取得するランディングページ - それはリダイレクトではなく転送先自身のサーバーの仕事です。リダイレクトは訪問者をどこに送るかを選択します。転送先は何をレンダリングするかを選択します。エッジに存在するルーティングロジックはあなたの認証セッションを見ることができず、それを無理に組み込もうとするとセッションをリダイレクトパスにリークするか(これはしません)エッジを通じてプロキシするか(レイテンシーバジェットのためしません)を要求します。バリアントはオリジンでレンダリングしてください。
統計的に厳密なA/Bテスト。 スマートリンクは訪問者ごとではなく、リクエストごとにルーティングします。訪問者が5分以内に同じデバイスから2回ランディングした場合、ランダム化されたルールの下で2つの異なる転送先を見る可能性があります。「モバイルトラフィックの50%をAに、50%をBに送る」には正しい動作ですが、「バリアントAが4週間のウィンドウでバリアントBよりもコンバートするかを測定する」には間違った動作です。後者には、安定したバリアントCookieと統計を適切に行う実験ツールが必要です。PostHog、GrowthBook、LaunchDarklyはすべてこれをします。私たちはしません。するつもりもありません - そのツールは別の仕事です。低ステークスのサンプリングにはround_robin のバリアントローテーションを使用し、結果を守る必要がある場合は実験プラットフォームを使用してください。
アイデンティティアウェアなルーティング。 スマートリンクは意図的にステートレスです。country | device | OS | language | time | referrer に対して評価し、それ以外は何もしません。ログインしたユーザーのティア、フィーチャーフラグ、または「この人は誰か」を調べることを要求する何かに基づいてルーティングする必要がある場合、リダイレクトパスは間違ったレイヤーです。オリジンでアイデンティティを解決して、そこからバリアントを提供してください。または、本当にリダイレクト時の決定が必要な場合は、API経由でユーザーごとの短縮リンクを発行してください - 認証されたすべてのユーザーが独自のスラグを得て、スラグの転送先は作成時点でそのユーザーに正しく、ホットパスでアイデンティティ解決を行う必要はありません。
次は何か#
自分のデータでルール形状を試してみたい場合、ドキュメントガイドでJSONスキーマとダッシュボードエディタを説明しています。ルールビルダーはダッシュボードの任意のリンクの編集ページにあります - Links → ⋯ → Targeting。
次のマイナーリリースで提供される2つの改善:languages のフォールバック階層(pt-BR が3つのルールを書かずに pt に、次に en にきれいにデグレードするように)と、ルールが重複している場合にライブになる前にダッシュボードが警告できるよう、リンク保存時の静的解析パス。どちらも実装作業で、スキーマの破壊的な変更はありません。サポートしていないルール形状があり、サポートすべきだと思う場合、フィードバックチャンネルはスマートリンク機能ページの下部にあります。
ブログの関連記事#
Elidoを試す
URLを貼り付けて短縮リンクを取得
登録不要。リンクは30日間有効。永久に保存するには登録してください。
Free、登録不要 · 1日あたり2件