πŸ”΄ Bad OTP Dashboard

dt = 2026-06-28 Β· single-day
Bad OTP / Cost
User Behavior
πŸ“– Data & lineage
Filter: all

Fail composition</> SQLserver

of total sends β€” failure is user-side

        
πŸ’‘ INSIGHTNO_VERIFY dominates, not wrong code. Carrier ~100% β€” fixing drop-off beats switching vendor.

Wasted spend by reason</> SQLserver

$ on sends that never verified

        

Verify fail rate by vendor</> SQLserver

carrier ~100% on all β€” gap is completion

        
πŸ’‘ INSIGHT~13 pt spread at equal delivery. Route high-NO_VERIFY traffic off the worst vendor.

Fail rate by country</> SQLserver

top corridors Β· Unknown (=NO_VERIFY) excluded

        

🎯 Action levers

P0
Reduce NO_VERIFY drop-off β€” App/UX + auto-fill, not a vendor switch. Biggest waste.
P0
Route high-NO_VERIFY traffic off the worst vendor toward Etisalat-class delivery.
P1
Trend + anomaly panel needs multi-day β€” wire to 122-day server history.

β‘  Funnel β€” send β†’ enter β†’ verify</> SQLclient

trace-deduped Β· 61.8% verify Β· 44.6% never enter

      
πŸ’‘ INSIGHTBiggest leak: "saw page, never typed" (31,478) β€” input friction, not delivery.

β‘‘ Verification failure reasons</> SQLclient

n = 14,881 failed traces

        
πŸ’‘ INSIGHT87% = wrong code. Help users mis-type less (auto-fill + clearer UI).

β‘’ Rate-limit blocks</> SQLclient

89,508 events = 36.4% of requests

        
πŸ’‘ INSIGHT1 in 3 blocked. Number Limit + Others dominate; thresholds look strict.

β‘£ Send β†’ verified total time</> SQLclient

distribution Β·

      
πŸ’‘ INSIGHT68% within 30s, 91% within 60s; tail ~9% over a minute.

β‘€ Top-50 countries β€” input vs verify/retry</> SQLclient

median seconds, sorted by total

      
πŸ’‘ INSIGHTTwo slows: Qatar verify/retry 34s; Iran input 38s.

β‘₯ Auto-fill coverage β€” platform Γ— version</> SQLclient

auto-fill is iOS-only Β· live-filtered by Platform + Version

        
πŸ’‘ INSIGHTAndroid = 0% (105k entries) β€” big lever. iOS 31.6%β†’35.8%.

⑦ Auto-fill vs manual β€” speed</> SQLclient

send β†’ filled/verified, seconds

        
πŸ’‘ INSIGHT0.7s vs 23s median β€” saves ~22s. iOS-only.

β‘§ Timestamp semantics β€” platform Γ— version</> SQLclient

same field, different meaning per platform β€” a tracking gap

      
PlatformVersiontotalrelativeepochnull
iOS4.12.016,4280%99%1%
iOS4.11.18,0880%85%15%
Android4.11.3104,91395%0%5%
Android4.11.118682%0%18%
both≀4.10β€”0%0%100%
πŸ’‘ INSIGHTiOS=epoch, Android=relative β€” not a version flip (rollout skew). Fix: split into input_duration_ms + event_ts.

⑨ Root causes & tracking gaps

  • πŸ”‘ Auto-fill only 4% overall, 0% on Android β€” highest-leverage fix.
  • Gap 1 β€” Block has no identity (no trace_id/uid) β†’ count only.
  • Gap 3 β€” auto-fill orphaned: Entered uses a fresh trace_id β†’ conversion unmeasurable until it reuses the session trace_id.
  • Gap 4 β€” timestamp semantics differ by platform; split the field.

🎯 Action items

P0
Add Android auto-fill (SMS Retriever + User Consent) β€” 0% today, saves ~22s/verify.
P0
Fix Gap 3 β€” reuse session trace_id on auto-fill Entered.
P1
Investigate Qatar delivery & slow corridors (Iran).
P1
Evaluate loosening rate-limit thresholds β€” 1 in 3 blocked.

πŸ“… Date range Β·Tab1

backend: checking…

🌍 Country ·Tab1

πŸ“‘ Send channel Β·Tab1

πŸ“± Platform Β·Tab2

🏷 Version ·Tab2

βš™ More

Cross-source note: Country/Channel exist only server-side, Platform/Version only client-side (no join key) β€” each filters its own tab. Multi-day + full client filtering come with the Grafana-backed build.