Deep Linking & Universal Links — Mobile

Deep Linking di Mobile App Deep linking memungkinkan URL membuka screen spesifik di app kamu — bukan hanya home screen. Ini penting untuk sharing content…

Deep link adalah link yang membuka satu layar tertentu di dalam aplikasi, bukan cuma membuka aplikasinya. Bu Rini mengirim pesan WhatsApp ke Mbak Wulan berisi link Order #13, dan ketukan di link itu langsung membuka layar Order #13. Bayangin nota cucian: "datang ke toko" itu membuka aplikasi, "ambil di rak 13" itu deep link. Dan kalau Mbak Wulan belum punya aplikasinya, link yang baik tetap membawanya ke tempat yang benar: halaman web Order #13.

🧪 Tebakan cepat: Universal Link sudah benar dan aplikasinya terpasang. Mbak Wulan mengetik https://laundryburini.id/order/13 di address bar Safari. Aplikasinya terbuka? Jawabannya ada di bagian "Universal Links di iOS".

Tiga jenis link ke Order #13

Link Jenis Aplikasi terpasang Belum terpasang
laundryburini://order/13 custom scheme Order #13 terbuka gak ada yang bisa membukanya
https://laundryburini.id/order/13 di iPhone Universal Link Order #13 terbuka halaman web Order #13
https://laundryburini.id/order/13 di Android App Link Order #13 terbuka halaman web Order #13

Custom scheme gampang dipasang, tapi aplikasi lain bisa mendaftarkan scheme yang sama, dan tanpa aplikasinya link itu buntu. Universal Link dan App Link adalah alamat HTTPS biasa yang dibuktikan milikmu lewat file di domainmu, jadi punya cadangan web.

Expo Router: link langsung ke layar

scheme: "laundryburini" sudah ada di app.json sejak pelajaran setup, dan Expo Router membuat rute dari file. Jadi tanpa konfigurasi apa pun, laundryburini://order/13 membuka src/app/order/[id].tsx dengan { id: '13' }. Expo Router menggabungkan host dan path dari link itu (order + /13) jadi order/13. Link HTTPS https://laundryburini.id/order/13 dibuang origin-nya, jadi /order/13, rute yang sama.

$ npx uri-scheme list
› iOS: Schemes for config: ./ios/LaundryBuRini/Info.plist
› laundryburini://
› id.laundryburini.app://

› Android: Schemes for config: ./android/app/src/main/AndroidManifest.xml
› laundryburini://
› https://

Itu hasil di project ini setelah npx expo prebuild. Prebuild juga mendaftarkan bundle ID sebagai scheme kedua, dan https:// muncul di Android karena App Link di bawah. Untuk mencoba di development build:

npx uri-scheme open laundryburini://order/13 --android
npx uri-scheme open laundryburini://order/13 --ios
adb shell am start -W -a android.intent.action.VIEW -d "laundryburini://order/13" id.laundryburini.app

Di Expo Go, scheme-nya milik Expo Go: exp://127.0.0.1:8081/--/order/13. Bagian setelah /--/ adalah path di aplikasimu. Link ke rute yang gak ada (misalnya laundryburini://pesanan/13) menampilkan layar "Unmatched Route" bawaan, atau layar milikmu di src/app/+not-found.tsx.

Universal Links di iOS

Dua sisi harus saling mengakui. Di aplikasi:

{ "expo": { "ios": { "bundleIdentifier": "id.laundryburini.app", "associatedDomains": ["applinks:laundryburini.id"] } } }

Prebuild menulisnya ke entitlements sebagai com.apple.developer.associated-domains berisi applinks:laundryburini.id (tanpa https://). Di web, file https://laundryburini.id/.well-known/apple-app-site-association:

{
  "applinks": {
    "details": [
      {
        "appIDs": ["A1B2C3D4E5.id.laundryburini.app"],
        "components": [{ "/": "/order/*", "comment": "Detail order dibuka di aplikasi" }]
      }
    ]
  }
}

Mengetik alamat langsung di address bar adalah navigasi di dalam browser, dan gak pernah membuka aplikasi. Safari membuka halaman webnya. Itu jawaban tebakannya. Universal Link bekerja saat link diketuk dari aplikasi lain: WhatsApp, email, Notes.

App Links di Android

{ "expo": { "android": { "package": "id.laundryburini.app", "intentFilters": [{
  "action": "VIEW",
  "autoVerify": true,
  "data": [{ "scheme": "https", "host": "laundryburini.id", "pathPrefix": "/order" }],
  "category": ["BROWSABLE", "DEFAULT"]
}] } } }

Prebuild menulis <intent-filter android:autoVerify="true"> dengan android:host="laundryburini.id" dan android:pathPrefix="/order" ke AndroidManifest.xml. Di web, https://laundryburini.id/.well-known/assetlinks.json, disajikan dengan content type application/json:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": { "namespace": "android_app", "package_name": "id.laundryburini.app", "sha256_cert_fingerprints": ["SHA256_SERTIFIKAT_DARI_EAS_CREDENTIALS"] }
}]

Kalau aplikasinya belum terpasang

Universal Link dan App Link jatuh ke browser, jadi https://laundryburini.id/order/13 harus benar-benar ada sebagai halaman web: status Order #13 setelah login, plus ajakan memasang aplikasi. Di iPhone, <meta name="apple-itunes-app" content="app-id=..."> di halaman itu memunculkan banner App Store. Custom scheme gak punya cadangan seperti ini, jadi kirim link HTTPS di WhatsApp dan email, bukan laundryburini://.

Jangan percaya id dari link

Siapa pun bisa membuat link laundryburini://order/12, dan #12 adalah order Pak Darto. Layar detail memeriksa bentuk id-nya, lalu bertanya ke server, yang cuma menjawab order milik akun yang login:

// src/app/order/[id].tsx
export default function DetailOrder() {
  const { id } = useLocalSearchParams<{ id: string }>();
  const idSah = /^\d{1,6}$/.test(id ?? ''); // link bisa berisi apa saja

  const { data, isPending, isError } = useQuery({
    queryKey: ['orders', id],
    queryFn: () => ambilOrder(id), // GET /api/orders/{id}: 404 untuk order orang lain
    enabled: idSah,
    retry: false,
  });

  if (!idSah || isError) return <Text>Order gak ketemu</Text>;
  if (isPending) return <ActivityIndicator />;
  return <Text>{data.nama}: {data.status}</Text>;
}

⚠️ Jebakan yang sering ketemu

TL;DR: laundryburini://order/13 (custom scheme) langsung membuka src/app/order/[id].tsx lewat Expo Router, tanpa konfigurasi, tapi buntu kalau aplikasinya gak ada. https://laundryburini.id/order/13 adalah Universal Link (iOS: associatedDomains: ["applinks:laundryburini.id"] plus /.well-known/apple-app-site-association dengan appIDs dan components, HTTPS tanpa redirect, diambil CDN Apple) dan App Link (Android: intentFilters dengan autoVerify: true plus /.well-known/assetlinks.json berisi package dan fingerprint SHA-256), yang jatuh ke halaman web kalau aplikasinya belum terpasang. Uji dengan npx uri-scheme open, adb shell am start, dan adb shell pm get-app-links; Universal Link diuji dengan mengetuk dari Notes, karena mengetik di address bar gak pernah membuka aplikasi. Jangan percaya id dari link: periksa bentuknya dan biarkan GET /api/orders/{id} menjawab 404 untuk order orang lain.

Yang akan kamu pelajari