Chuyển đến nội dung chính

Khắc Phục Sự Cố Deep Link

Bạn sẽ học: Cách tự chẩn đoán khi tích hợp không như mong đợi — bắt đầu từ triệu chứng bạn quan sát được, rồi dùng matchMethod / missReason trong response làm la bàn. Hầu hết sự cố tự gỡ được mà không cần mở ticket.

Công cụ chẩn đoán số 1: đọc response

Trước khi đoán, hãy in nguyên response của /track/open ra log và đọc ba trường:
matchMethod   →  nó đã làm gì (universal_link / app_link / clipboard / install_referrer)
missReason    →  vì sao trượt (chỉ có khi link == null)
platform      →  server nhận diện ios / android (null = User-Agent không rõ)
link != null nghĩa là KHỚP. Khi đó matchMethod cho biết khớp qua đường nào. link == null nghĩa là TRƯỢTmissReason cho biết lý do. Mọi chẩn đoán bên dưới đều xoay quanh hai trường này.

Đặt kỳ vọng đúng: deferred là best-effort

no_candidateclipboard_empty là chuyện bình thường, không phải bug của bạn. Deferred deep linking phụ thuộc vào hành vi người dùng (có dán clipboard không, có tới store qua chính link Li2 không) và giới hạn nền tảng. Một tỷ lệ trượt nhất định là bản chất của cơ chế, không phải lỗi code. Đừng cố “sửa cho hết trượt” — hãy phân biệt trượt do người dùng/nền tảng (bình thường) với trượt do cấu hình sai (cần sửa, xem bên dưới).

Chẩn đoán theo triệu chứng

App không mở (vẫn ra trình duyệt) — luồng immediate

Thiếu xác minh App Link. Kiểm tra:
adb shell pm get-app-links your.package.name
# Phải hiển thị: your-domain.com → verified
  • Nếu thấy 1024 (chưa xác minh): SHA-256 trong dashboard không khớp chứng chỉ ký APK đang cài (debug vs release khác nhau — thêm cả hai).
  • Thiếu android:autoVerify="true" trong intent-filter.
  • Buộc xác minh lại: adb shell pm verify-app-links --re-verify your.package.name.
  • assetlinks.json có thể bị cache; xem Cấu Hình Domain.

Mọi lời gọi /track/open trả 401

Đây là lỗi phổ biến nhất. Gần như luôn là sai loại key:
  • Dùng publishable key li2_pk_... (Settings → Analytics → Publishable Key), không dùng server API key X-Li2-API-Key. Endpoint mobile chỉ chấp nhận li2_pk_*.
  • Android: thiếu LI2_PUBLISHABLE_KEY trong local.propertiesBuildConfig.LI2_PUBLISHABLE_KEY rỗng → header rỗng → 401. Thêm key rồi build lại.
  • Lỗi xác thực ở middleware không kèm error_code — branch theo HTTP status 401, đừng so khớp chuỗi message. Xem API: body lỗi.
missReasonBình thường hay cần sửa?Ý nghĩa & hành động
no_candidateThường bình thườngKhông tìm thấy click khớp: người dùng không tới store qua chính link Li2, hoặc bản ghi Redis đã hết hạn (TTL). Chỉ cần lo nếu mọi lượt deferred đều no_candidate → kiểm tra trang trung gian có thực sự gieo li2_cid (iOS) / li2_dl (Android) không.
clipboard_emptyBình thường (iOS)Người dùng chạm Paste nhưng clipboard không chứa link Li2. Không sửa được từ phía app.
clipboard_deniedBình thường (iOS)Người dùng chặn quyền dán. Trên iOS 16+ dùng Li2PasteButton để tránh alert; iOS 15 không tránh được.
opt_outBình thườngNgười dùng chủ động bấm “Bỏ qua”. Hành vi đúng.
cross_tenant_blockedCần xem lạiHostname thuộc org khác — bị chặn theo cô lập tenant. Kiểm tra li2Domains / deepLinkDomains bạn gửi có đúng là domain của org bạn không.
Cô lập tenant ở luồng deferred trả 200 + cross_tenant_blocked, KHÔNG phải 403 — để không lộ việc hostname có thuộc org khác hay không. Chỉ luồng immediate mới trả 403 khi domain không thuộc org. Xem API.

iOS: Li2PasteButton luôn xám / disabled

  • Clipboard đang rỗng → đây là behavior đúng của Li2PasteButton. Bạn phải có nút thay thế cho nhánh clipboardHasContent == false (gọi submitPasteControlEmpty()), nếu không người dùng bị kẹt và outcome empty không bao giờ được gửi. Xem ConsentSheet trong Tích hợp App.
  • Tự dựng UIPasteControl trong fullScreenCover bị xám: phải gán control.target tường minh + override canPaste(_:). Đây là lý do nên dùng Li2PasteButton của SDK thay vì tự bọc.
Bình thường nếu Universal Link tới trong cửa sổ grace (~250ms). UL “thắng”: cờ hasReceivedUniversalLink được bật, nhánh deferred bị bỏ qua, và sheet tự dismiss. Không cần sửa.

Android: deferred luôn no_candidate dù cài qua Play Store

  • adb install APK cục bộ KHÔNG có referrer. Install Referrer chỉ trả chuỗi thật khi cài qua Play Store (internal-test track). Đây là giới hạn nền tảng, không phải bug.
  • Người dùng phải tới Play Store qua chính link Li2 (URL mang tham số referrer). Tự tìm app trên store → không có li2_dlno_candidate.
  • App phải gọi InstallReferrerClientlần mở đầu. Truy vấn một lần rồi lưu kết quả — đừng phụ thuộc gọi lại nhiều lần.
  • Không có cửa sổ “mở ngay kẻo mất”: Play lưu referrer lúc cài và giữ lại; bạn lấy được ở lần mở đầu dù mở bằng cách nào.

Conversion: lead/sale báo lỗi

LỗiNguyên nhân / cách sửa
.noClickIdAvailable (iOS)Gọi attributed/anonymous khi chưa có match. Chạy deep-link match trước, hoặc dùng biến Direct.
.missingExternalId (iOS)identify thiếu external_id. Cấp user id ổn định.
403Gói/feature conversion chưa bật cho org hoặc link.
400 (customer not found)Cấp email/name/phone để tự tạo khách hàng, hoặc ghi lead trước sale.
Lead & sale rơi vào hai hồ sơThiếu identify (iOS) / lead __identify__ (HTTP) trước sale. Xem Đo Lường Chuyển Đổi.

Cây quyết định nhanh

Response về?
├─ Không (timeout/network)  → retry TRONG CÙNG lần mở; đừng retry xuyên nhiều lần mở
├─ 401                       → sai loại key (xem mục 401 ở trên)
├─ 403                       → org thiếu gói Pro, HOẶC immediate domain không thuộc org
├─ 200, link != null         → KHỚP ✓  (matchMethod cho biết qua đường nào)
└─ 200, link == null         → TRƯỢT — đọc missReason:
                               ├─ no_candidate / clipboard_* / opt_out → thường bình thường
                               └─ cross_tenant_blocked → kiểm tra domain bạn gửi

Khi nào cần mở ticket

Tự gỡ được hầu hết bằng các bước trên. Mở ticket tới [email protected] khi:
  • AASA/assetlinks báo “Live & correct” trên dashboard nhưng device vẫn không xác minh sau khi đã chờ qua cache (~6h iOS).
  • /track/open trả 5xx lặp lại (lỗi server — kèm timestamp + response body).
  • matchMethod/missReason trả giá trị không có trong tài liệu.

Bước tiếp theo

API: POST /track/open

Tra cứu đầy đủ matchMethod, missReason, mã trạng thái và body lỗi.

Cấu Hình Domain

Kiểm tra file AASA / assetlinks và vấn đề caching.