Intelligence·Engagement·Defense
Kotlin SDK for analytics, behavior targeting, crash capture, install attribution, push, and in-app messages — from one init() call. One dependency. Universal across View and Compose apps.
One dependency in Gradle. One initialize call in your Application. Everything else is opt-in.
// settings.gradle.kts dependencyResolutionManagement { repositories { google() mavenCentral() } }
// app/build.gradle.kts dependencies { implementation("com.dijji:dijji-core:1.0.0") // Optional — pull only what you use implementation("com.dijji:dijji-messages:1.0.0") // in-app UI implementation("com.dijji:dijji-push:1.0.0") // FCM glue }
// YourApp.kt class YourApp : Application() { override fun onCreate() { super.onCreate() Dijji.init(this, siteKey = "ws_abc123") } }
That’s it. Rebuild, launch. Your first app_open and screen_view events will land on your dashboard within 30 seconds.
ws_* key appears in Site Settings → Mobile. Free during alpha.
These fire without a single extra line of code. Turn any of them off via the config block on Dijji.init.
| Event | When it fires |
|---|---|
| app_install | First launch on this device — Play Install Referrer resolves UTM / source |
| app_open | Process foreground (cold + warm starts) |
| app_background | Last activity backgrounds — queue flushes here |
| session_start | First event after ≥30 min idle — configurable |
| session_end | Idle timeout or background, whichever fires first |
| screen_view | Activity onResume — name = class simple name |
| app_crash | Uncaught exception caught before the process dies — breadcrumbs attached |
| $identify | Your Dijji.identify() call |
Eleven methods. No builders, no config trees, no overloaded patterns to learn. Ruthlessly small on purpose.
| Method | Purpose |
|---|---|
| Dijji.init(ctx, siteKey) | Required once — typically in Application.onCreate |
| Dijji.identify(userId, traits) | Tie subsequent events to a user. Traits merge into the user profile. |
| Dijji.track(name, props) | Custom event. Properties are free-form key/value. |
| Dijji.screen(name, props) | Manual screen — only when auto-capture name is wrong |
| Dijji.setUserProperty(k, v) | Persistent property attached to every future event |
| Dijji.setUserProperties(map) | Bulk form of setUserProperty |
| Dijji.unsetUserProperty(k) | Remove a previously-set super-property |
| Dijji.reset() | Logout — rotates visitor_id, flushes queue first |
| Dijji.flush() | Force queue send (before known app exit) |
| Dijji.setEnabled(bool) | Per-user privacy kill — survives restarts |
| Dijji.visitorId() | The opaque per-install UUID for server-side correlation |
fun onLoginSuccess(user: User) { Dijji.identify( userId = user.id, traits = mapOf( "email" to user.email, "plan" to user.plan, "signup_date" to user.createdAt ) ) Dijji.setUserProperty("role", user.role) Dijji.track("login_completed", mapOf("method" to "phone_otp")) }
Every event batch the SDK sends carries a full snapshot of device + user + network + power context. The server UPSERTs one row per install with the freshest values — so you segment against one well-indexed table, not scans over millions of events.
Targeting a low-memory user on 3G at 15% battery becomes a one-line segment query — because every signal is a first-class column, not buried in events.
Set once, and every future event for this install carries the value. Your dashboard segments filter on these without the app ever re-sending.
// After a successful subscription Dijji.setUserProperty("plan", "pro") Dijji.setUserProperty("mrr_inr", 499) // Now every subsequent track() and screen() carries plan=pro + mrr_inr=499.
Type your intent in plain English. Dijji compiles it into a structured rule you can review and refine. No flowcharts, no JSON, no rule builder to master.
| Capability | How it works |
|---|---|
| Authoring UI | Natural-language composer + structured view — no flowcharts to master |
| Web + mobile in one rule | Same rule engine across platforms; actions adapt to where the user is |
| AI copy generation | Claude-written, per-user context, A/B across variants automatically |
| Autonomous segment discovery | Weekly surfacing of “here’s a cohort worth targeting” |
| Pricing | Bundled per workspace — no enterprise sales call |
The engine evaluates these against every incoming event and profile snapshot. Mix any matcher with any action.
| Matcher | Fires when |
|---|---|
| screen_view | User lands on a named screen |
| screen_sequence | User hits A → B → C within window |
| event_fired | A named custom event fires |
| event_count ≥ | User has fired event ≥ N times ever / in window |
| session_start | First event of a new session |
| session_count | User’s Nth session overall |
| inactive_days | Hasn’t opened in N days |
| install_referrer_match | Came from specific campaign |
| push_opened | Just tapped a push — chain actions |
| deep_link_opened | Came via a specific deep link |
| crash_recent | Crashed in last session |
| device_match | Manufacturer / model / OS ≤ X |
| app_version_match | On version < X (upgrade nudge) |
| geo_match | Country / city match |
| trait_match | trait.plan = "pro", MRR > 999, etc. |
| context_match | battery < X, on_wifi, dark_mode on, low_memory |
| Action | What happens |
|---|---|
| push | FCM notification (optionally Claude-written per user context) |
| in_app_banner | Top / bottom strip inside active session, non-blocking. image_url renders 40dp thumb. |
| in_app_bottom_sheet | Material bottom sheet with optional 16:9 hero image, cards + buttons |
| in_app_modal | Full-screen overlay for critical prompts, optional 16:9 image |
| in_app_hero v1.2 | Full-bleed takeover dialog — 4:3 image, gradient veil, primary + secondary CTA |
| in_app_nps v1.2 | 0–10 colour-graded score sheet, fires __dijji_nps_submitted with score |
| in_app_reactions v1.2 | Emoji feedback bar (2–5 emojis), fires __dijji_reaction_submitted |
| in_app_countdown v1.2 | Live ticker urgency modal, ISO/relative deadline, optional ended_text |
| in_app_chat | Ghost Bot opens as a chat sheet |
| deep_link | Navigate the app to a specific screen |
| silent | Log outcome only — ghost arm for A/B learning |
Production-safe from day one. You don’t need an app update to disable Dijji — flip mobile_enabled in site settings and every SDK instance silently stops within 30 seconds. The server enforces the same toggle as a backstop.
Phased rollout: ship with rollout_pct = 1, let a few installs warm things up, ramp 5 → 25 → 50 → 100 as crash-free rate holds. SDK hashes visitor_id mod 100 so the same device stays on the same side of the gate across restarts.
// Overrides, all optional — sensible defaults baked in Dijji.init(this, siteKey = "ws_abc123") { autoCaptureScreens = true // default on sessionTimeout = 30.minutes // industry norm flushInterval = 30.seconds // how often queue sends maxQueueSize = 500 // offline cap captureCrashes = true captureInstallReferrer = true debugLogging = false // turn on for development }
Both are driven by the same trigger engine — no second product, no second dashboard.
dijji-push dependencydijji-messages dependencyidentify(). The SDK never reads contacts, SMS, location, or account info.Dijji.setEnabled(false) silences the SDK on that device permanently until re-enabled.Dijji.reset() rotates visitor_id locally; dashboard has a “delete this user” control that drops all events within 24h.mobile_enabled = 1 and rollout_pct = 100 in Site Settings → Mobile.debugLogging = true in the init config and watch logcat | grep Dijji.INTERNET permission isn’t being stripped by a manifest merger conflict.com.dijji.sdk.DijjiInstaller AndroidX Startup provider isn’t being excluded../gradlew :app:dependencies.consumer-rules.pro auto-applies — no rules to copy.| Milestone | ETA | What ships |
|---|---|---|
| v1.0 (alpha) | Live | Core ingestion, rich user data, auto-capture, install referrer, kill switch |
| v1.1 | 2 weeks | Universal in-app renderers, FCM push dispatcher, ProGuard mapping upload |
| v1.2 | 4 weeks | AI trigger composer (natural-language → rule), visual rule builder, Ghost Bot mobile chat |
| v1.3 | 6 weeks | NDK crash handler, Room-backed offline queue, Navigation screen naming |
| v1.4 | 8 weeks | iOS SDK parity, Flutter + React Native wrappers, Unity evaluation |
| v2.0 | TBD | The Brain — realtime autonomous decisioning, weekly outcome learning loop |