Skip to content
GitHubGet started

Apps

Dashboard

Register iOS and Android apps, with every field, its validation, the status chips, the Auto-fill, Verify and Send test actions, and which app's settings the server actually applies.

The Apps screen, at https://app.dectog.com/dashboard/apps, holds the identifiers DecTog needs to route taps and open your app. Its header reads “Register your iOS and Android apps. Their identifiers power store routing, deep links and the Universal Links / App Links files DecTog serves for you.”

An Add app button opens the editor. While the editor is closed, a status line shows “Saved ✓”, “Deleted ✓” or the last error.

Each registered app is a card with two-letter initials, the name, the iOS bundle ID or Android package (or “No identifiers yet”), Edit, Delete and five status chips. A chip is green when its condition holds and gray otherwise.

Chip Green when Hover text
iOS links Both the iOS bundle ID and the Apple Team ID are set. Universal Links: iOS bundle ID + Apple Team ID
Android links The Android package and at least one SHA-256 fingerprint are set. App Links: package + SHA-256 fingerprints
Store routing An App Store URL or a Play Store URL is set. App Store / Play Store URL
Scheme Shows the scheme: myapp:// when both platforms share one, iOS a:// · Android b:// when they differ, or No scheme. Custom URL scheme for deep links
Fallback URL A fallback URL is set. Web fallback for desktop and missing destinations

The oldest app is the account’s default app. It serves links created with Default app, every temporary link, and links whose app was deleted.

The editor is titled Edit <name>, Register your first app or Register an app, with the subtitle “Only the name is required — fill in each platform as you set it up.” On wide screens a side menu jumps to the six sections below. The editor is always open while the account has no app.

Editing a saved app opens with a checklist the server computes on every visit; nothing in it is stored.

Step Done when
App identifiers saved An iOS bundle ID and Team ID, or an Android package and at least one SHA-256 fingerprint
Universal Links file passes Apple’s rules The apple-app-site-association file served for your account lists this app’s <Team ID>.<bundle ID>, covers every path, is JSON under 128 KB with no byte-order mark, and is served over https with application/json
App Links file passes Google’s rules assetlinks.json grants handle_all_urls to this app’s package with every saved fingerprint, each a real SHA-256 (32 colon-separated hex bytes), over https with application/json
The SDK has reported An install of this app (matched by bundle ID or package) came from an identified SDK build; the version is shown
A link was tapped Any link of the account recorded a web tap
First install registered An install of this app reached the server
First install attributed to a link One of them was credited to a link; the slug is shown
First event received The account received an identify, lead, conversion or custom event
Webhook configured (optional) An active webhook takes this app’s events (its own, or an account-wide one); not counted in the total

A platform you have not set up is greyed out and not counted. Each step that is not done says what to do next. On a local deployment (http://localhost) both file steps stay open, because Universal Links and App Links only work over https.

On the hosted service, or any deployment on a real domain, Check <username>.<root> fetches both files from your live link host in your browser, without following redirects. It reports a redirect, a 404, the wrong content type, or a host that does not answer at all, which usually means the DNS records for the apex and * are missing or not proxied.

Section text: “The app’s name and the web page links fall back to when the app can’t serve them (desktop continue button, last mobile fallback).”

Field What to enter Rules
App name Placeholder My App. Required when creating: App name is required. When editing, an emptied name keeps the old one.
Fallback URL (optional) Placeholder https://myapp.com. The web page a tap lands on when nothing else applies: desktop visitors (instead of the QR page) and phones with no store URL to go to. Links created with App fallback URL (default) inherit it. http(s), or fallback_url must be a valid http(s) URL.

Section text: “Bundle ID and Team ID generate your Universal Links file; the store URL and scheme route taps.”

Field What to enter Rules
iOS bundle ID Placeholder com.example.myapp. Must look like com.company.app: at least two dot-separated parts of letters, digits and underscores, each starting with a letter. Error: ios_bundle_id must look like com.company.app.
Apple Team ID Placeholder 10-char team id. Hint: “Required for Universal Links”. Exactly 10 uppercase letters or digits. Error: ios_team_id must be a 10-character Apple Team ID (e.g. 8H7C9JL2K3).
App Store URL Placeholder https://apps.apple.com/app/id123. Where iPhone taps go when the app is not installed. The host must be exactly apps.apple.com. Error: ios_store_url must be an apps.apple.com URL.
iOS app scheme The scheme only, shown with a :// suffix (placeholder myapp). ⓘ “The custom URL scheme declared in the iOS app’s Info.plist (CFBundleURLSchemes). DecTog builds deep links as scheme://username/slug — type the scheme only.” A letter followed by letters, digits, +, - or .; a pasted trailing :// is removed. http, https, ws, wss, javascript, file, data, blob, about and intent are rejected with ios_app_scheme must be a custom app scheme — the browser handles http/https/javascript itself, so it can never open the app. Other invalid values get ios_app_scheme must be a URL scheme (letters, digits, +, -, .) without :// — e.g. myapp.

Below the fields, Universal Links file /.well-known/apple-app-site-association has a Verify button and an ⓘ bubble with a four-step guide: the bundle ID and Team ID generate the file once both are saved; add an Associated Domains entitlement in Xcode; rebuild and reinstall, because iOS reads the file when the app is installed; and custom-scheme links only open from a direct user tap, never from a redirect. The bubble, and the setup prompt its ⧉ Copy for AI button copies (with your domain, username, bundle ID and Team ID filled in), name the entitlement as the explicit host, applinks:your-username.dectog.com, and warn against the wildcard: for applinks:*.dectog.com iOS fetches the file from the parent domain, and https://dectog.com/.well-known/apple-app-site-association answers 400 with Subdomain not found in host, because only the your-username.dectog.com host (or ?u=your-username) identifies the account. The platform side is covered in Platform setup.

Section text: “Package name and SHA-256 fingerprints generate your App Links file; the store URL and scheme route taps.”

Field What to enter Rules
Android package Placeholder com.example.myapp. Same shape as the bundle ID. Error: android_package must look like com.company.app.
Play Store URL Placeholder https://play.google.com/store/apps/details?id=…. Where Android taps go when the app is not installed. The host must be exactly play.google.com. Error: android_store_url must be a play.google.com URL.
Android app scheme Placeholder myapp, with the :// suffix. ⓘ “The android:scheme registered in the app’s intent filters. Leave it equal to the iOS one if both platforms share a scheme.” The same rules and messages as the iOS scheme, prefixed android_app_scheme.
Facebook App ID (optional) Placeholder 1234567890123456. ⓘ “The SDK reads it from here at start-up and uses it for Meta’s on-device install referrer (Facebook and Instagram apps, Android). A fbAppId set in DectogConfig in your app takes precedence.” Free text, trimmed. Served to the SDK by GET /api/v1/sdk-config. See Deterministic attribution.
SHA-256 fingerprints (one per line) Placeholder AA:BB:CC:…. Hint: “Include your release / Play App Signing key, not only the debug key.” Each line must be 32 hex byte pairs separated by colons. Values are stored in uppercase; blank lines are dropped. Error: SHA-256 fingerprints must be 32 hex byte pairs separated by colons (AA:BB:…).
Other Android stores: Huawei AppGallery URL, Samsung Galaxy Store URL, Xiaomi GetApps URL, vivo store URL ⓘ “Optional. Devices from these brands are sent to their own store instead of Google Play — e.g. Huawei phones without Google services. Each store passes the install referrer back to the SDK, so installs still attribute deterministically. Leave empty to always use Google Play.” Huawei: a host under appgallery.huawei.com, appgallery.cloud.huawei.com or url.cloud.huawei.com. Samsung: galaxystore.samsung.com, apps.samsung.com or galaxy.store. Xiaomi: global.app.mi.com or app.mi.com. vivo: any http(s) URL. Errors read huawei_store_url must be a appgallery.huawei.com / appgallery.cloud.huawei.com / url.cloud.huawei.com URL and so on, or vivo_store_url must be a valid http(s) URL. An OEM URL is used only for phones of that brand and works without a Play Store URL.

Below the fields, App Links file /.well-known/assetlinks.json has its own Verify button and ⓘ guide: the package and fingerprints generate the file once both are saved; add an https intent filter with android:autoVerify="true" for each tenant host, listed explicitly because intent filters take no wildcards; Chrome verifies at install or update, and until then taps still open the app through an intent:// redirect carrying your scheme and package. ⧉ Copy for AI copies the prompt with your package and fingerprints filled in. How brands are detected and store URLs tagged is in App stores and OEM routing.

Section text: “The react-native-dectog config plugin writes the Associated Domains and App Links setup above into the native projects. This app’s entry, filled in:”. Below it, the plugin entry for this app, ready for plugins in app.json: your username (the test environment’s while the dashboard shows it), the deployment’s link root when it is not dectog.com, the account’s custom link domain when it has one, and the iOS scheme (else the Android one) as scheme. Copy copies it. Run npx expo prebuild after adding it; the two file checks above confirm the server side, and Dectog.diagnostics() in the app the device side. See React Native and Expo.

Section text: “How your links look when shared on social media or in messaging apps. Used for every link without its own preview.”

Field What to enter Rules
Image URL Placeholder https://…/preview.jpg. Hint: “JPG or PNG. Recommended size 1200 × 630 px (shown as a large card).” http(s): og_image_url must be a valid http(s) URL.
Title Placeholder My App. Hint: “Recommended 30 to 60 characters. Maximum 150 characters.” The box does not stop you; the server rejects more than 150 characters with og_title must be at most 150 characters.
Description (optional) A short text. The box stops at 150 characters; the server enforces the same limit.

A Live preview card renders the three values, captioned “How the app default looks when a link is shared on social media or messaging apps.” The per-link editor gives the same 1200 × 630 px hint; each platform crops as it likes. See Social previews and QR.

Auto-fill from fallback URL appears in the section header when the Fallback URL is an http(s) address and at least one of the three preview fields is empty. It reads “Fetching…” while running, fills only the empty fields from the page’s og: and twitter: tags, and reports ✓ Filled from your fallback URL — review, then save. or ✕ followed by the server’s error: No title, description or image found on that page, Enter a valid public http(s) URL (private and loopback hosts are refused), Couldn't reach that URL, or a message naming the HTTP status the page returned. The fetch follows redirects, gives up after 8 seconds or 512 KB, and cuts titles and descriptions to 150 characters. Nothing is saved until you save the form.

Shown for a saved app. Section text: “Signed POSTs to your servers (HMAC-SHA256 in X-Dectog-Signature) for installs, conversions, opens, referrals and link changes. Every delivery is logged and retried for a day.” The list holds the webhooks that receive this app’s events: the app’s own and the account-wide ones. Each row shows its URL, a status chip (On, the number of failures in a row such as 3 failed in a row, or Off with the reason), whether it takes this app or every app, and its events.

Button What it does
Deliveries The last 20 deliveries: time, event, Delivered with the HTTP status, Retry with the time of the next attempt, or Failed with the error, the attempt number, the start of the response, and Resend.
Send test Delivers a webhook.test event now and opens the log; a failure is shown above the list and does not count toward the thresholds.
Rotate secret Asks first, then shows the new signing secret once; the old one stops working at once.
Turn off, Turn on Stops or resumes deliveries. Turning on resets the failure count, and pending retries go out with the next hourly run.
Delete Asks first, then deletes the webhook and its log.

Add webhook asks for the URL, Events of this app or Events of every app, and the events, each with a short note (click.recorded, one delivery per tap, is not ticked at first). Add webhook then shows the signing secret once: “The signing secret. Copy it now: it will not be shown again.” The envelope, the events, retries and verification code are in Webhooks.

Shown for a saved app. Turn on store notifications creates the app’s two URLs:

Item Meaning
App Store Server Notifications URL Paste it in App Store Connect → the app → App Information → App Store Server Notifications, Version 2. Needs the app’s iOS bundle ID.
Google Play Pub/Sub push endpoint The endpoint of a Pub/Sub push subscription on the topic named in Play Console → Monetization setup, with authentication on. Needs the app’s Android package.
Pub/Sub service account The service account of that subscription. Save account stores it; pushes signed for any other account are refused.
New URLs Replaces both URLs after a confirmation; the old ones stop working at once.
Turn off Deletes both URLs after a confirmation.
Refresh Reloads the list below.

Below the buttons, the last 20 notifications: time received, store, notification type (with subtype and a non-production environment), transaction id, and the result (recorded, updated, duplicate, ignored, unmatched, test, rejected). What each notification records is on Revenue.

Section text: “Attribution behaviour. Everything here is off by default.”

Setting Control What it does, as the screen describes it
Strict fraud mode Switch “Off: installs that trip a fraud rule (emulator, impossible click-to-install timing, install velocity per IP, click storm, stale referrer) keep their attribution and carry the flags. On: flagged installs count as organic — the click they claimed stays consumed either way.” With the switch on, a flagged install is stored as unmatched, but the server keeps the referrer source, the confidence and the matched slug on the record as evidence. Neither the app’s verdict nor the webhook names the slug of an uncredited install.
Probabilistic match Switch, on by default “On: when no store referrer, copied link or Meta referrer names the click, the server compares the install with recent taps from the same network and credits a unique, corroborated match. Off: installs of this app are matched by those deterministic signals only, the comparison never runs, and its link pages stop reading the device settings. Apple’s rules prohibit fingerprinting; turn this off if your App Store review requires it.” The switch is read from the app the install belongs to (its package name or bundle ID).
OEM store referrers Switch, on by default “The SDK also reads the Huawei, Samsung, Xiaomi and vivo store referrers on Android. It picks this up at start-up; a value set in DectogConfig in the app takes precedence.”
Pasteboard read at first launch Select: Platform default, On, Off “Default: on for iOS while a page of yours copies the link (tap-to-store or the interstitial, on the app or on a link), since only those taps leave a link to read; off otherwise, and always off on Android. The read shows Apple’s paste alert on iOS 16+. The SDK picks this up at start-up; a value set in DectogConfig in the app takes precedence.”
Mobile beacon interstitial Switch “Off: mobile taps get an instant redirect to the store or app. On: taps see a brief “Opening the app…” page that records the screen profile on the click, which sharpens install matching. Adds roughly half a second.” When iOS tap-to-store is on, the row shows an Android only badge and continues “iPhone taps are handled by iOS tap-to-store (its page sends the same beacon), so this switch now affects Android only.”; otherwise it continues “On iPhone, iOS tap-to-store takes over when it is on; Android taps still get this page.”
iOS tap-to-store Switch “Off: iPhone taps go straight to the App Store. On: taps see a one-button page whose “Get the app” tap copies the link to the clipboard before opening the App Store. The SDK reads it on first launch, so iOS installs attribute deterministically instead of by IP. Inside Instagram and Facebook the page offers “Open in app” first. There is no automatic redirect: Safari only lets the page copy from a tap. On iPhone this replaces the beacon interstitial.” The page is used only when the tap’s destination is the App Store.
Low-entropy attribution window Number box, 1 to 720, placeholder 2, suffix “hours” “Hours an IP-only click (no device model or screen profile to compare, or an install on mobile data) stays matchable. Shorter is safer on shared carrier networks. Empty uses the deployment default (2 hours); clicks whose device model or screen profile can be compared with the install keep the full 24-hour window.” The server accepts a whole number from 1 to 720 or an empty box; anything else gets low_entropy_window_hours must be a whole number of hours between 1 and 720. The effective value never exceeds the wide window of 24 hours.
MMP click handoff Switch, and a Media source (pid) box (optional, letters, digits, ., -, _, up to 100) shown when on “For a migration from AppsFlyer, Singular or Adjust: when a link sends visitors to one of their tracking links (onelink.me, sng.link, app.adjust.com, adj.st), add DecTog’s click id as clickid, so both tools report the same tap and their verdicts can be compared. A clickid or pid already in the link wins.” See Running both for a while.
Pasted-link and Meta window Number box, 1 to 720, placeholder 168, suffix “hours” “Hours a copied link (iOS tap-to-store, paste button) or a Meta install referrer still earns credit. An older click sends the user to the link but counts the install as organic, flagged stale_clipboard or stale_meta; with strict fraud mode on it does not even route. Empty uses the deployment default (168 hours, 7 days). Store referrers keep 30 days.” The server accepts a whole number from 1 to 720 or an empty box.
Re-engagement window Number box, 1 to 720, placeholder 168, suffix “hours” “Hours after one of this app’s links re-opened the installed app during which purchases and other events count for that link instead of the link that brought the install. Empty uses the deployment default (168 hours, 7 days).” Applied when the dashboard reads the numbers, so a change also moves past credit.

Strict fraud mode and both windows are read from the app the install concerns (see the note at the top of this page). The interstitial and tap-to-store switches belong to the app a link uses. The fraud rules, windows and confidence levels are explained in How attribution works and Attribution internals.

A sticky bar appears at the bottom once the form differs from what is saved, with Save changes (or Add app for a new app) and Cancel. While nothing is wrong it reads “Changes apply to new link taps right after saving.” or “New apps can be edited any time.” A rejected save keeps the bar up and replaces that text with the server’s message. On success the editor closes and the status line shows “Saved ✓”.

Updates are partial on the server: a field left out keeps its value, and an emptied field clears it (except the name). Identifier fields are validated after trimming but saved exactly as typed, so avoid leading or trailing spaces.

Each Verify button fetches the account’s well-known file through the dashboard host with ?u=your-username, which returns exactly what https://your-username.dectog.com/.well-known/… serves publicly. It checks the saved configuration of every app in the account, not the unsaved editor, and shows one line:

Button Result
Universal Links file ✓ <n> app ID(s) served, or ✕ No app IDs configured when no app has both a bundle ID and a Team ID.
App Links file ✓ <n> package(s), SHA-256 fingerprints present; ✕ <n> package(s), MISSING fingerprints when no package has a fingerprint; or ✕ No packages configured.
Either ✕ Endpoint replied <status>: <error> (the server answers 404 with Configuration not found while no app qualifies) or ✕ Fetch failed: <reason>.

The AASA file lists every app that has both a bundle ID and a Team ID, as TEAMID.bundle, under applinks and webcredentials. The assetlinks file lists every app that has a package, with its fingerprints (an empty list when none are set). Both are described in Well-known, SEO and routing.

The trash icon asks Delete app "<name>"? Links using it will fall back to your default app. This cannot be undone. Links bound to the app lose their binding and are served by the oldest remaining app from the next tap on; so do link templates that named it, and the links made from them afterwards. The webhooks limited to the app are deleted with their delivery logs, and its store notification URLs stop working; account-wide webhooks stay. Clicks and installs recorded for the app stay. The status line shows “Deleted ✓”.