W marcu wydrukowaliśmy 18 000 ulotek na launch produktu na rynek DACH. Jeden krótki link z tyłu, trzy regionalne strony landing, na które chcieliśmy kierować odwiedzających: /de dla gości z Niemiec, /fr dla małej frakcji francuskojęzycznej, /en dla wszystkich pozostałych. Lead marketingowy zadał oczywiste pytanie: drukujemy trzy rodzaje ulotek czy jeden?
Jeden. Link robi routing.
„Smart link" to pojedynczy krótki URL, którego cel jest obliczany podczas przekierowania, a nie w momencie tworzenia linku. Jest jeden slug. Jest kilka możliwych celów. Decyzja zapada w tym samym handlerze, który w innym przypadku wydałby zwykłe 302 - żadnego osobnego serwisu do wywołania, żadnego shima JS na stronie landing, żadnego dodatkowego hopa. Ten wpis opisuje, jak to wygląda pod maską, sześć wymiarów routingu Elido i przypadki, w których powinieneś sięgnąć po inne narzędzie.
Trzy rzeczy, którymi smart link nie jest#
Ludzie sięgają po smart linki z trzech różnych wcześniejszych doświadczeń, a kompromisy są w każdym inne.
Zwykłe przekierowanie. Jeden slug, jeden cel, zero logiki. Handler przekierowania robi cache lookup i pisze 302. Nie pobijecie tego pod względem latencji; nie możecie też tego warunkować. To jest podłoga - wszystko bardziej skomplikowane kosztuje coś.
Smart link na edge. Jeden slug, kilka możliwych celów, tiny krok ewaluacji reguł wstawiony między cache lookup a odpowiedź. Ponieważ reguła żyje w tym samym procesie co cache lookup, koszt wynosi poniżej milisekundy (0,3ms p50 / 1ms p95 w przypadku Elido). Odwiedzający widzi jedną rundę HTTP. Cache przeglądarki nie jest zatruty, bo odpowiedzi 302 domyślnie nie są cachowalnie zgodnie z RFC 7234 §4.2.2 - fakt, który ma tu znaczenie, bo routing per-request ma sens tylko wtedy, gdy każde żądanie może wybrać własny cel.
Router A/B w JavaScript na stronie landing. Neutralna strona HTML się renderuje, JS analizuje navigator.userAgent lub serwis geo-IP, a następnie window.location = '/foo'. To jest najgorszy z trzech wariantów. Odwiedzający widzi render HTML, potem przekierowanie, potem właściwą stronę - co najmniej jedna dodatkowa runda, często dwie, jeśli geo lookup jest third-party. Indeksowanie SEO jest mętne, bo crawlery widzą neutralną stronę. Przeglądarki blokujące cookies i wtyczki prywatności psują połowę z JS. Informacje o wydaniu Apple Intelligent Tracking Prevention 2.3 wskazują dokładnie ten wzorzec: client-side tracking linki przez document referrer są ograniczane, a obejście wymaga uczestnictwa po stronie serwera. Jeśli dziś routujesz w JS, już płacisz rachunki.
Właściwym miejscem na decyzję routingową jest ten sam hop, który już wydaje przekierowanie. Tak właśnie działają smart linki na edge.
Dlaczego żyje na edge - budżet latencji#
Warstwa przekierowań Elido ma twardy budżet latencji: p50 5ms, p95 15ms przy trafieniu cache, bez uwzględnienia TLS handshake. Ta liczba nie jest aspiracyjna - wszystko, co nas ponad nią pcha, jest wyjmowane. Synchroniczny SQL na hot path, kompilacja regex per request, blokujące I/O na zdarzeniu kliknięcia: wszystko znikło, wszystko przeniesione do workerów cold-path.
Dwa powody, dla których ten budżet istnieje:
- Sieci mobilne nakładają własny podatek. Przewodnik Apple „Reducing Network Latency" pokazuje, jak opóźnienia sieci komórkowej narastają w łańcuchach przekierowań. Każdy dodatkowy hop dodaje RTT, który sieć odwiedzającego już zwiększyła. Im mniej hopów dodajemy, tym mniej ich sieć ich karze.
- Bliskość edge to prawdziwa dźwignia. Primer Cloudflare o routingu po stronie edge ujmuje to tak samo: najtańsza decyzja to ta podjęta w tym samym procesie co twórca odpowiedzi, w POP najbliżej odwiedzającego. Nie jesteśmy jedyni, którzy robią routing na edge; co jest wyjątkowe, to bundlowanie go w skracz URL zamiast proszenia o deployment osobnej funkcji Workers / Lambda@Edge.
Gdybyśmy przekazali ewaluację reguł do serwisu downstream - powiedzmy, hipotetycznego „rules-api" osiągalnego przez HTTP - dodalibyśmy same-region round trip na każde żądanie. W regionie to minimum ~5ms (przeskok w tym samym regionie przez sieć prywatną), a w ruchu międzyregionowym ogon się bardzo brzydko rozkłada. p95 15ms nie przeżywa tej rundy. Dlatego reguły smart linków są inline, w binarce edge, ewaluując na podstawie skompilowanych matcherów zbudowanych przy ładowaniu linku do cache. Cały silnik reguł to około 400 linii Go.
To ciasne sprzężenie wyjaśnia też, dlaczego możemy edytować reguły w czasie rzeczywistym: zmiany reguł propagują się przez kanał pub/sub pamięci podręcznej w pamięci (link:invalidate), który subskrybuje każdy POP edge. L1 LRU eksmituje w ciągu sekundy od publikacji, następne żądanie repopuluje z L2, a nowa reguła jest live. Więcej o tym poniżej.
Sześć wymiarów routingu#
Smart linki Elido matchują na sześć rzeczy. Każda mapuje na konkretny wejściowy sygnał dostępny dla edge per request.
Kraj. Dwuliterowy ISO 3166-1 alpha-2, wyprowadzony z IP odwiedzającego przez geoip. Przydatny, gdy masz regionalne sklepy i per-country uplift w konwersji uzasadnia złożoność routingu. Klasyczna pułapka tutaj to podróżnicy - Niemiec na wakacjach w Hiszpanii trafi na cel dla Hiszpanii, jeśli routujesz wyłącznie po kraju. Jeśli preferencja językowa liczy się bardziej niż lokalizacja geograficzna, routuj po languages. Omawiamy pełny przepływ geoip we wpisie o prywatności analityki - IP jest skracane przed storage, więc strona RODO pozostaje czysta.
Urządzenie. mobile, tablet, desktop, parsowane z ciągu User-Agent w czasie żądania. Przypadek użycia, po który marketingowcy po to sięgają: bannery app-install kierujące do App Store na iOS, Play Store na Android i strony marketingowej na desktop. Na co uważać: ciągi User-Agent na iPad są ruchomym celem od kiedy iPadOS zaczął domyślnie prezentować UA desktopowego Safari, a nasze wykrywanie tabletu to uwzględnia, ale nie jest 100% na każdej wersji przeglądarki. Jeśli różnica między ruchem tabletowym a desktopowym liczy się dla Ciebie w pieniądzach, instrumentuj cel i weryfikuj.
System operacyjny. ios, android, macos, windows, linux. To samo źródło User-Agent co urządzenie, węższy podział. Przypadek deep-linku: kieruj odwiedzających iOS na Universal Link, który przechwytuje aplikacja i spada do App Store; kieruj Android do Play Store z zachowanymi danymi referrera. To właśnie dla tego zbudowaliśmy integrację Apple App Site Association.
Język. Podstawowy tag języka z nagłówka Accept-Language odwiedzającego. Kody ISO 639-1 jak de, fr, pt. Pułapka: Accept-Language to preferencja przeglądarki, która często nie zgadza się z IP geo. Francuz-emigrant w Berlinie dostaje country: DE, languages: ["fr", "en"] - jeśli chcesz go na /fr, routuj po języku; jeśli chcesz go na sklepie niemieckim, bo A/B testujesz zlokalizowane ceny, routuj po kraju. Ustal reguły w odpowiedniej kolejności.
Pora dnia i dzień tygodnia. Okno HH:MM w dowolnej strefie czasowej IANA plus bitmapa days_of_week. Oferty ograniczone czasowo - strona landing „happy hour", która uruchamia się o 17:00 Europe/Berlin pon.–pt. i cofa do zwykłej strony poza tym oknem - to naturalne zastosowanie. Okno time_start / time_end obsługuje zawijanie przez północ (22:00 → 02:00), co brzmi oczywisto, ale nas zaskoczyło przy portowaniu silnika reguł z prototypu, który tego nie obsługiwał. Pełny schemat jest w przewodniku po smart linkach.
Host referrera. Część hostowa nagłówka Referer, znormalizowana. Przydatna do celów świadomych partnerów: odwiedzający przyjeżdżający z partner.example dostają co-brandowaną stronę landing; wszyscy inni dostają domyślną. Mniej przydatna niż kiedyś - nowoczesne przeglądarki agresywnie usuwają Referer, gdy strona odnosząca ustawia Referrer-Policy: no-referrer albo gdy nawigacja przekracza konteksty HTTPS w sposób niepozwolony przez politykę. Traktuj reguły referrera jako miękki sygnał, nigdy jako uwierzytelnienie.
To wszystko. Sześć wymiarów pokrywa decyzje routingowe marketingu, jakie widzieliśmy w trzyletich rozmowach z klientami. Celowe pominięcia to tożsamość użytkownika (nie znamy jej na przekierowaniu), dowolne nagłówki HTTP (koszt-do-payoff nie jest tam dla kilku zespołów, które pytały) oraz losowe podziały (zamiast tego użyj rotacji wariantów, która jest osobną funkcją).
Semantyka first-match; fallback zawsze wymagany#
Reguły to tablica. Edge przechodzi przez nie po kolei. Pierwsza reguła, której blok match jest w pełni spełniony, wygrywa i jej destination_url staje się celem przekierowania. Najwyższy poziom destination_url linku to bezwarunkowy fallback. Odmawiamy tworzenia smart linku bez niego - smart link nigdy nie produkuje 404, z założenia.
Minimalny kształt:
{
"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"
}
]
}
Odwiedzający z DACH trafiają na /de, bo reguła 1 matchuje pierwsza. Francuz-emigrant w Berlinie ma country=DE, więc też trafia na /de - reguła 1 matchuje zanim reguła 2 dostanie szansę. Jeśli chcesz Francuza-emigranta na /fr, zmień kolejność reguł tak, żeby reguła językowa była sprawdzana jako pierwsza. Kolejność w dashboardzie to kolejność ewaluacji.
Dwie rzeczy, które z tego wynikają, warte głośnego powiedzenia:
- Szersze reguły idą na końcu. Reguła bez warunków
matchmatchuje wszystko; jeśli jest pierwsza, żadna reguła poniżej nigdy nie odpali. Dashboard waliduje to i ostrzega, ale API nie, więc reguły budowane skryptowo potrzebują sprawdzenia poprawności. - Wykluczenie wzajemne leży po Twojej stronie. Jeśli dwie reguły obie matchują jednego odwiedzającego, pierwsza wygrywa cicho. Brak błędu, brak flagi, brak metryki. Rozważaliśmy emitowanie ostrzeżenia przy ładowaniu linku, gdy dwie reguły są wykrywalne jako nakładające się - to jest na roadmapie dla następnego wydania minor. Na razie: czytaj reguły od góry do dołu i ufaj kolejności.
Koszt: propagacja inwalidacji cache#
Każda decyzja routingowa ma okno propagacji. Reguły smart linków edytowane w dashboardzie propagują się przez cache L1 na wszystkich trzech POP-ach Elido w około 1 sekundę na happy path. Mniej więcej, bo:
- L1 LRU w każdym POP przechowuje linki z regułami z TTL 60 sekund (architektura cache jest udokumentowana tutaj). TTL to górna granica - nawet bez publikacji invalidate, stary wpis zniknie w ciągu minuty.
- Publikacja invalidate jest przez pub/sub pamięci podręcznej w pamięci. POP-y w regionie UE i USA Wschód współdzielą klaster pamięci podręcznej; Azja-Pacyfik ma własny. Propagacja cross-region to zasadniczo latencja replikacji pamięci podręcznej plus przetwarzanie pub/sub subskrybenta, co przez ostatni kwartał w naszych metrykach wynosi poniżej 1 sekundy p99.
- POP, który stracił subskrypcję pamięci podręcznej, cofa się do TTL 60 sekund. Alertujemy na stratę subskrypcji; on-call ma 5 minut buforowanych kliknięć zanim WAL się włączy.
Tłumaczenie: dla przepływów marketingowych, gdzie 60 sekund nieaktualnego routingu jest w porządku, nie musisz o tym myśleć. Dla przepływów, gdzie nieaktualność ma znaczenie - rotacja zastrzeżeń prawnych, podział kohorty rozliczeniowej gdzie zły cel obciąża złą walutą - ruchem jest najpierw status=disabled, potem ponowne włączenie po minucie, potem opublikowanie nowej reguły. Dodaliśmy endpoint GET /v1/links/{id}/status, żeby pipeline CI mógł pollować zakończenie propagacji przed przełączeniem czegoś downstream.
Kiedy nie używać smart linku#
Trzy przypadki, gdzie właściwym narzędziem nie jest smart link.
Server-side rendering celu jest lepszy. Jeśli wariant musi być wstrzyknięty do odpowiedzi HTML - powiedzmy, lokalizacja cen zależna od stanu uwierzytelnienia odwiedzającego lub strona landing, która pobiera hero specyficzny dla kohorty z Twojego CMS - to jest zadanie dla własnego serwera celu, a nie przekierowania. Przekierowanie wybiera, gdzie wysłać odwiedzającego; cel wybiera co wyrenderować. Logika routingowa żyjąca na edge nie widzi Twojej sesji auth, a wbudowanie jej wymagałoby albo wycieku sesji do ścieżki przekierowania (czego nie zrobimy) albo proxowania przez edge (czego nie robimy ze względu na budżet latencji). Renderuj warianty na origin.
Statystycznie rygorystyczne testy A/B. Smart linki routują per request, nie per odwiedzający. Jeśli odwiedzający ląduje dwa razy w ciągu pięciu minut z tego samego urządzenia, może zobaczyć dwa różne cele przy losowej regule - co jest właściwym zachowaniem dla „wyślij 50% ruchu mobilnego do A i 50% do B", ale złym dla „zmierz, czy wariant A konwertuje lepiej niż wariant B przez 4-tygodniowe okno". Dla tego drugiego potrzebujesz stabilnego ciasteczka wariantu i narzędzia do eksperymentów, które robi statystyki poprawnie. PostHog, GrowthBook i LaunchDarkly to wszystkie robią. My nie robimy i nie zamierzamy - tooling to inna praca. Używaj rotacji wariantów z round_robin do próbkowania niskiego ryzyka i sięgaj po platformę eksperymentów, gdy musisz obronić wynik.
Routing świadomy tożsamości. Smart linki są celowo bezstanowe. Ewaluują na podstawie country | device | OS | language | time | referrer i niczego innego. Jeśli musisz routować na podstawie poziomu zalogowanego użytkownika, jego feature flag lub czegokolwiek wymagającego wyszukania „kim jest ta osoba", ścieżka przekierowania to zła warstwa. Rozwiąż tożsamość na origin i serwuj wariant stamtąd. Albo, jeśli naprawdę potrzebujesz decyzji w czasie przekierowania, mintuj per-user krótkie linki przez API - każdy uwierzytelniony użytkownik dostaje własny slug, cel sluga jest poprawny dla tego użytkownika w czasie tworzenia i nigdy nie musisz robić rozwiązywania tożsamości na hot path.
Co dalej#
Jeśli chcesz wypróbować kształt reguł na własnych danych, przewodnik w docs prowadzi przez schemat JSON i edytor dashboardu. Builder reguł jest dostępny pod stroną edycji każdego linku w dashboardzie - Links → ⋯ → Targeting.
Dwa usprawnienia lądujące w następnym wydaniu minor: hierarchia fallback dla languages (żeby pt-BR czysto degradowało do pt, potem do en, bez pisania trzech reguł) oraz przejście statycznej analizy przy zapisie linku flagujące nakładające się reguły, żeby dashboard mógł ostrzegać przed uruchomieniem reguły na żywo. Oba to praca implementacyjna, bez przełamujących zmian schematu. Jeśli masz kształt reguły, którego nie obsługujemy i uważasz, że powinniśmy, kanał feedbacku jest na dole strony funkcji smart linków.
Powiązane na blogu#
Wypróbuj Elido
Wklej URL, otrzymaj krótki link
Bez rejestracji. Link działa 30 dni. Zarejestruj się, aby zachować go na zawsze.
Za darmo, bez rejestracji · 2 dziennie