marketing

Deep linking khi seeding traffic vào app: setup + measure 1 ngày xong

Deep linking khi seeding traffic vào app: setup + measure 1 ngày xong

Deep linking khi seeding traffic vào app: setup + measure 1 ngày xong

Tôi sẽ kể chuyện thật. Tháng 2/2025, tôi launch 1 app couple. Spend 8 triệu cho 5 KOC TikTok seeding. Mỗi KOC gắn link bio trỏ về App Store.

Kết quả: TikTok analytics báo 47,000 lượt click. App Store Connect báo 3,200 install. Conversion rate 6.8% — nghe có vẻ ổn.

Nhưng vấn đề thật bắt đầu sau install: 0% user vào đúng landing screen của campaign. Mỗi user vào app đều thấy onboarding mặc định — không có context "bạn đến từ KOC X", không có promo code auto-fill, không có direct route đến feature đang trend.

Kết quả 30 ngày sau: D7 retention chỉ 8% (vs benchmark 15-20%). Lý do? User vào app, không hiểu app này có gì khác KOC nói, churn ngay tuần đầu.

Đây là lý do deep link quan trọng. Bài này tôi sẽ giải thích deep link, universal link, app link, deferred deep link — và quan trọng nhất: setup hôm nay, đo conversion ngày mai.

Quên khái niệm tech document đi. Cho indie dev Việt 2026, deep link = link đưa user vào đúng màn hình trong app, kèm theo context từ campaign.

Ví dụ:

  • Link bình thường: https://myapp.com → mở browser, end of story
  • Deep link (app đã cài): https://myapp.com/promo/koc-mai → mở app, vào màn hình promo, hiện code KOC Mai
  • Deferred deep link (app chưa cài): cùng link → App Store → user install → mở app → vẫn nhớ context KOC Mai → vào đúng màn hình promo

Cái cuối cùng (deferred) là chỗ 90% indie Việt fail.

1. Custom URL scheme — kiểu cũ, đừng dùng nữa

myapp://promo/koc-mai

Vấn đề:

  • Không work nếu app chưa cài (user thấy error)
  • Không work khi click từ Safari/Chrome (security)
  • Không share được qua iMessage/Zalo
  • Bị Apple/Google deprecate dần

Bỏ qua. Không dùng năm 2026.

https://myapp.com/promo/koc-mai

Đây là standard năm 2026. Dùng HTTPS URL thật:

  • App đã cài → mở thẳng app
  • App chưa cài → mở web (hoặc redirect App Store)
  • Share được qua mọi channel
  • SEO friendly
  • Apple/Google đều support official

Đây là cái bạn nên setup.

Là universal/app link PLUS khả năng nhớ context khi user phải install app trước. Implement qua MMP (Branch, Adjust, AppsFlyer).

  • User click link https://myapp.com/promo/koc-mai
  • App chưa cài → vào App Store
  • User install + mở app
  • App đọc Branch SDK → biết user đến từ link koc-mai
  • Auto navigate user vào promo screen + fill code

Đây là magic. Đây là cái KOC seeding cần.

Bước 1: Tạo Associated Domain

Ở Apple Developer portal:

  1. Vào Identifiers → chọn App ID
  2. Bật Associated Domains capability
  3. Save

Trong Xcode (hoặc Flutter ios/Runner):

  1. Signing & Capabilities → + Capability → Associated Domains
  2. Thêm: applinks:myapp.comapplinks:www.myapp.com

Bước 2: Upload Apple App Site Association (AASA) file

Tạo file apple-app-site-association (KHÔNG có extension) tại https://myapp.com/.well-known/apple-app-site-association:

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "TEAMID.com.yourcompany.myapp",
        "paths": [
          "/promo/*",
          "/share/*",
          "/invite/*",
          "/post/*"
        ]
      }
    ]
  }
}

Lưu ý quan trọng:

  • File phải serve qua HTTPS
  • Content-Type phải là application/json
  • Không redirect — Apple cấm
  • KHÔNG đặt extension .json

Laravel route:

// routes/web.php
Route::get('/.well-known/apple-app-site-association', function () {
    return response()->json([
        'applinks' => [
            'apps' => [],
            'details' => [[
                'appID' => env('APPLE_TEAM_ID') . '.com.yourcompany.myapp',
                'paths' => ['/promo/*', '/share/*', '/invite/*', '/post/*'],
            ]],
        ],
    ])->header('Content-Type', 'application/json');
});

Bước 3: Test

Dùng Apple's validator: https://search.developer.apple.com/appsearch-validation-tool

Nhập URL https://myapp.com/promo/test123 → kiểm tra xem AASA file có valid không.

Bước 1: Thêm intent filter vào AndroidManifest.xml

<activity android:name=".MainActivity">
    <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:scheme="https"
              android:host="myapp.com"
              android:pathPrefix="/promo" />
        <data android:scheme="https"
              android:host="myapp.com"
              android:pathPrefix="/share" />
    </intent-filter>
</activity>

android:autoVerify="true" là magic ingredient — buộc Android verify domain ownership.

Bước 2: Upload assetlinks.json

Tạo file tại https://myapp.com/.well-known/assetlinks.json:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.yourcompany.myapp",
    "sha256_cert_fingerprints": [
      "AB:CD:EF:..."
    ]
  }
}]

Lấy SHA-256 fingerprint từ keystore của bạn:

keytool -list -v -keystore ~/upload-keystore.jks -alias upload

Với Google Play App Signing (recommended 2026), thêm fingerprint từ Play Console → Setup → App Integrity.

Bước 3: Verify

Dùng Google Digital Asset Links tester: https://developers.google.com/digital-asset-links/tools/generator

Hoặc test direct:

adb shell pm verify-app-links --re-verify com.yourcompany.myapp
adb shell pm get-app-links com.yourcompany.myapp

Output phải có verified (không phải legacy_failure).

Với universal/app link basic, bạn handle khi app đã cài. Để handle khi app chưa cài + giữ context → cần Branch (hoặc Adjust, AppsFlyer).

Tôi recommend Branch cho indie Việt vì:

  • Free tier 10K MAU
  • Setup nhanh nhất (1 giờ)
  • Dashboard analytics tốt
  • Support deferred deep link out-of-box

Bước 1: Tạo Branch account + app

  1. Đăng ký https://branch.io (free)
  2. Add new app → Configure iOS + Android
  3. Set Branch link domain (vd: myapp.app.link)

Bước 2: Add Branch SDK

Flutter:

dependencies:
  flutter_branch_sdk: ^8.0.0

React Native:

npm install react-native-branch

Native iOS/Android: theo doc Branch.

Bước 3: Initialize Branch trong app

Flutter ví dụ:

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    _initBranch();
  }

  void _initBranch() {
    FlutterBranchSdk.initSession().listen((data) {
      if (data.containsKey('+clicked_branch_link') && 
          data['+clicked_branch_link'] == true) {
        // User đến từ Branch link
        final source = data['source'] ?? 'unknown';
        final promoCode = data['promo_code'];
        final targetScreen = data['target_screen'];
        
        _navigateWithContext(targetScreen, source, promoCode);
      }
    });
  }
}

Qua Branch dashboard hoặc API:

curl -X POST https://api2.branch.io/v1/url \
  -H 'Content-Type: application/json' \
  -d '{
    "branch_key": "key_live_xxx",
    "channel": "tiktok",
    "feature": "koc_seeding",
    "campaign": "launch_couple_app_q1_2026",
    "data": {
      "source": "koc_mai",
      "promo_code": "MAI20",
      "target_screen": "promo_screen",
      "$desktop_url": "https://myapp.com",
      "$ios_url": "https://apps.apple.com/app/idXXX",
      "$android_url": "https://play.google.com/store/apps/details?id=XXX"
    }
  }'

Response: { "url": "https://myapp.app.link/abc123" }

Link này gửi cho KOC → KOC put trong bio TikTok.

Mỗi ngày sau khi KOC seeding, check 3 dashboard:

Branch dashboard

Key metrics:

Metric Ý nghĩa Good benchmark
Link clicks Tổng click vào Branch link KOC reach × 2-5%
Install attribution Install có Branch attribution 60-80% click → install
Deferred deep link CTR User vào đúng screen sau install > 70%
Re-engagement User click lại link khi đã có app 10-20%

Firebase Analytics

Custom events bạn nên track:

  • deep_link_received — app nhận deep link
  • deep_link_navigated — user thực sự thấy target screen
  • promo_code_applied — promo từ deep link được apply
  • signup_from_deeplink — signup happen sau khi đi qua deep link

Custom backend tracking

Đây là chỗ tôi recommend mạnh: log event ở backend của bạn ngoài Branch:

// Khi app gọi API signup
class SignupController extends Controller {
    public function store(SignupRequest $request) {
        $user = $this->authService->signup($request->validated());
        
        // Log attribution
        if ($request->has('branch_source')) {
            $user->attribution()->create([
                'channel' => $request->input('branch_source'),
                'campaign' => $request->input('branch_campaign'),
                'promo_code' => $request->input('branch_promo'),
            ]);
        }
        
        return new UserResource($user);
    }
}

Bằng cách này, bạn có first-party attribution data không phụ thuộc bất kỳ 3rd party — important post-iOS 17 ATT.

Common pitfalls — đã ăn đủ rồi

Pitfall 1: AASA file bị cache nặng

Apple cache file AASA trong vài ngày. Nếu bạn deploy sai → fix → vẫn không work → đợi 7 ngày hoặc:

  1. Xóa app khỏi device
  2. Restart device
  3. Reinstall app từ App Store (không phải Xcode)
  4. Test lại

Sau khi deploy assetlinks.json, app build và install qua Play Store. App build local (debug) không verify App Link → click link vẫn ra browser thay vì app.

Để test debug build, dùng:

adb shell am start -a android.intent.action.VIEW \
  -d "https://myapp.com/promo/test123" com.yourcompany.myapp

Nếu setup cả Branch domain (myapp.app.link) + Universal Link domain (myapp.com) cùng lúc:

  • Link Branch (myapp.app.link/abc) → Branch SDK handle
  • Link own domain (myapp.com/promo/x) → Universal Link handle, Branch không thấy

Solution: route own domain qua Branch bằng cách dùng custom domain trong Branch:

  1. Branch dashboard → Configuration → Link domains
  2. Add app.myapp.com (subdomain riêng)
  3. Update CNAME DNS record
  4. Mọi link app.myapp.com/x → Branch attribute
  5. myapp.com/x (main website) → web bình thường

Zalo wrap link qua redirect. Universal Link không work qua redirect.

Solution: dùng Branch link (myapp.app.link/abc) thay vì own domain — Branch xử lý redirect đúng.

Quay lại app couple đầu bài. Sau khi tôi setup deep link đầy đủ + redo campaign với cùng 5 KOC:

Trước (no deep link):

  • 5 KOC × 8 triệu = 40 triệu total
  • 47,000 click → 3,200 install (6.8% CTR)
  • D7 retention: 8%
  • 30-day revenue: 5.2 triệu
  • ROI: -87%

Sau (có deep link + deferred):

  • 5 KOC khác × 8 triệu = 40 triệu total
  • 52,000 click → 3,800 install (7.3% CTR — slight boost)
  • D7 retention: 19% (gấp 2.4 lần)
  • 30-day revenue: 22 triệu
  • ROI: -45%

Vẫn lỗ campaign — nhưng giảm lỗ 50%. Và quan trọng nhất: user retention healthier → LTV cao hơn → break-even ở month 4 thay vì "không bao giờ".

Lý do duy nhất khác: deep link đem user vào đúng promo screen với code auto-fill. User thấy KOC nói có code → vào app code đã có sẵn → trust tăng → retain.

Setup checklist 1 ngày — copy paste mà làm

Sáng (3-4h)

  • Tạo Branch account free tier
  • Configure iOS + Android trong Branch dashboard
  • Setup Associated Domain (iOS) + Intent Filter (Android)
  • Deploy AASA file lên myapp.com/.well-known/
  • Deploy assetlinks.json lên myapp.com/.well-known/

Chiều (3-4h)

  • Add Branch SDK vào app
  • Code _initBranch + navigation handler
  • Code event tracking cho deep link
  • Setup backend logging attribution

Tối (1-2h)

  • Tạo 3-5 test link cho campaign sắp tới
  • Test full funnel: click link (app chưa cài) → install → mở app → check landing screen + context
  • Verify event xuất hiện trên Branch dashboard + Firebase + backend

Deep link không phải kênh đem install — nó là multiplier cho mọi channel. Khi bạn implement:

  • KOC seeding: conversion tăng 30-60%
  • Email campaign: CTR tăng 2-3x (vì user vào đúng screen)
  • Push notification: re-engagement 5x
  • Referral built-in: viral coefficient tăng 0.3-0.8 điểm

Tôi đã viết riêng 10 growth hack startup early-stage Việt Nam 2026 — trong đó deep link là foundation cho ít nhất 4 hack.

Tổng kết

Deep linking không sexy. Không một blog post nào về "How I grew my app to 1M users" nói về deep link. Nhưng nó là sự khác biệt giữa:

  • 5000 click → 100 install retain → 1 paying user
  • 5000 click → 350 install retain → 50 paying user

10x revenue chỉ vì user vào đúng màn hình trong app.

1 ngày setup. Lãi cả đời app.

Seeding traffic chất + measure đúng = winning combo

Deep link giúp bạn đo seeding traffic. Nhưng bạn cần traffic chất đầu vào trước. KOC seeding thật, beta tester thật, install thật từ user Việt — không phải bot.

Đây là chỗ GoSeedUp đóng vai trò:

  • KOC review app: micro-influencer Việt thật, content có TikTok bio link dẫn về deep link của bạn — measure 100% được conversion
  • Seeding install: 100-500 install thật, vào qua deep link → backend log attribution full
  • Closed Testing job: 12-20 beta tester real device — kiểm tra deep link work trên thiết bị khác nhau trước khi launch ads

Tôi đã dùng cho cả 4 app gần nhất. KOC + deep link là combo thắng. Đăng job lên GoSeedUp hôm nay, deep link work ngày mai, conversion measure được tuần sau.

#deep-link #universal-link #branch-io #seeding #attribution #app-marketing