@apex-inc/capacitor-plugin
v0.2.0
Published
Apex Capacitor plugin — iOS/Android attribution, events, deep linking, SKAN, and offline-tolerant tracking for Capacitor apps.
Maintainers
Readme
@apex-inc/capacitor-plugin
Apex Capacitor plugin — iOS and Android attribution, events, deep linking, SKAN, and offline-tolerant tracking for Capacitor apps.
Ships alongside apex.js (the web snippet) so a Capacitor app gets unified identity and events across WebView + native APIs with one dependency pattern.
Scope. This plugin is for Capacitor apps. Native iOS (Swift), native Android (Kotlin), React Native, and Flutter apps need their own SDKs — see https://apex.inc/docs/mobile/which-sdk.
Try it in 5 minutes. The sample app is a three-screen Capacitor + React app that exercises every API in this plugin.
git clone,npm install,npm run dev, watch events land in your Apex dashboard.
Install
npm install @apex-inc/capacitor-plugin
npx cap syncInitialize
Call initialize() once at app startup, before any other plugin method.
import { Apex } from "@apex-inc/capacitor-plugin";
await Apex.initialize({
projectKey: "prj_your_key",
// Optional:
// apiUrl: "https://api.apex.inc",
// sessionTimeoutMinutes: 30,
// offlineQueueMaxSize: 1000,
// testMode: false,
// debug: false,
});Track events
await Apex.track({
type: "app_open",
data: { from: "push_notification" },
});
// In-app purchase — typed payload
await Apex.track({
type: "in_app_purchase",
purchase: {
productId: "com.example.app.pro_monthly",
amount: 9.99,
currency: "USD",
transactionId: "abc123",
},
});Every event gets a client-generated UUIDv4 id automatically. Server-side idempotency means replayed events never double-count.
iOS App Tracking Transparency
// Present the ATT prompt once (no-op on Android).
const { status } = await Apex.requestTrackingAuthorization();
// Check status later without prompting.
const { status: current } = await Apex.getTrackingStatus();Advertising identifiers
// Returns IDFA (iOS, ATT authorized), GAID (Android), or fallback.
const { id, fallback } = await Apex.getAdvertisingId();
if (!id && fallback === "idfv") {
console.log("Using IDFV fallback — user denied ATT");
}SKAdNetwork conversion values (iOS 4.0+)
await Apex.updateConversionValue({
fineValue: 42,
coarseValue: "high",
});Deep links
// Cold start: read the URL that opened the app (if any).
const { url } = await Apex.getInitialDeepLink();
// Warm-start / subsequent links while running:
await Apex.addListener("deepLink", ({ url }) => {
handleRoute(url);
});Sessions
const { sessionId } = await Apex.startSession();
await Apex.addListener("sessionEnd", ({ sessionId, durationSeconds }) => {
console.log(`Session ${sessionId} ended after ${durationSeconds}s`);
});Offline durability
Events are persisted to IndexedDB (web), Core Data (iOS), or Room (Android). If the device is offline, they queue up to the configured offlineQueueMaxSize (default 1000). When the network returns, the plugin drains the queue in batches with exponential-backoff retry.
const { count, oldestEventAt } = await Apex.getQueueSize();
// Manually trigger a flush (rarely needed — happens automatically):
const { flushed, remaining } = await Apex.flushQueue();Test mode
// At init:
await Apex.initialize({ projectKey: "prj_test", testMode: true });
// Or toggle at runtime:
await Apex.setTestMode({ enabled: true });Test-mode events are stored separately on the server and never pollute production analytics.
Web fallback
The plugin runs in a browser or PWA too — identifiers return null, ATT is a no-op, events still flow to the server via the normal offline queue. This lets you run shared code paths between web + mobile without Capacitor.isNativePlatform() checks everywhere.
License
Apache-2.0 — see LICENSE. See also the project plan document for the full MMP roadmap.
