pex

Getting Started with Apex Mobile

Track installs, attribution, sessions, and in-app events from your Capacitor app with the @apex-inc/capacitor-plugin. This guide walks you through installing the plugin, initializing it at startup, and verifying the connection on the Apex dashboard.

Info

Using something other than Capacitor? See Which SDK do I need? for the matrix of Capacitor / React Native / native iOS / native Android / Flutter options. This guide is Capacitor-specific.

Info

Want to see it running first? Clone the apex-incorporated/capacitor-sample-app repo — it's a three-screen Capacitor + React app that exercises every plugin API. Point it at your project key, run npm run dev, and watch events land in your dashboard's debug console within 30 seconds.

Prerequisites

Before you start, you'll need:

  • A Capacitor 6+ app (iOS, Android, or both)
  • Node 18+ and npm
  • Your project key from the Apex dashboard → Settings → Snippet
  • For production testing: an Apple Developer account (iOS) and/or a Google Play Developer account (Android) — see the account checklist below

Install the Plugin

npm install @apex-inc/capacitor-plugin

Then sync native dependencies:

npx cap sync

That updates your ios/ and android/ folders so the native modules are wired up.

Initialize at App Startup

Call Apex.initialize() once at app startup, before any other method. A good place is your root component's mount hook, or a boot file run before React/Vue/Angular mounts.

import { Apex } from "@apex-inc/capacitor-plugin";

await Apex.initialize({
  projectKey: "pk_live_your_key_here",
  // Optional overrides:
  // apiUrl: "https://api.apex.inc",
  // sessionTimeoutMinutes: 30,
  // offlineQueueMaxSize: 1000,
  // testMode: false,
  // debug: false,
});
ParameterTypeDescription
projectKeyrequiredstringYour Apex project key. Find it in Settings → Snippet.
apiUrlstringBase URL of your Apex instance. Defaults to https://api.apex.inc.
sessionTimeoutMinutesnumberMinutes of inactivity before a session ends. Default 30.
offlineQueueMaxSizenumberMaximum events held in the offline queue before FIFO eviction. Default 1000.
testModebooleanRoute events to the test-event store (excluded from production analytics). Default false.
debugbooleanLog verbose SDK activity to the console. Default false.

Track Your First Event

Once initialized, send an app_install event when the user first opens your app, and app_open on every subsequent launch.

import { Apex } from "@apex-inc/capacitor-plugin";

// In your boot file, after initialize():
const isFirstLaunch = await checkFirstLaunch(); // your own logic
if (isFirstLaunch) {
  await Apex.track({ type: "app_install" });
}
await Apex.track({ type: "app_open" });

The plugin auto-fills id (UUIDv4 for idempotency), timestamp, sessionId, device context, IDFA/GAID (when available), and install referrer (Android). All you provide is the type and any custom data.

Tip

Event IDs are generated client-side so network retries don't double-count. If the same event.id arrives twice within 24 hours, the server deduplicates automatically.

iOS — Request Tracking Permission

On iOS 14.5+ you must ask for App Tracking Transparency before IDFA is available. Call requestTrackingAuthorization() once after onboarding — not at install — to maximize opt-in rate.

const { status } = await Apex.requestTrackingAuthorization();
// status: "authorized" | "denied" | "restricted" | "not-determined"

Even if the user denies ATT, attribution still works — the plugin falls back to IDFV plus probabilistic matching (IP + user-agent + time-window fingerprint). See Attribution for the full waterfall.

Verify the Connection

Open Integrations in your dashboard. The Apex Mobile card under "Apex Integrations" should transition from amber "Needs setup" to blue "Connected" within a few seconds of your first event arriving.

If it stays amber after a few minutes, here's the checklist:

Confirm `initialize()` completed

Enable debug: true in the initialize options and look for [apex-capacitor] initialized in your console. No log means initialize() was never called — double-check your boot path runs before any track().

Inspect the offline queue

Call Apex.getQueueSize() — if the count is growing, events are being recorded but can't reach the server. Check your apiUrl setting and network connectivity from the simulator/device.

Check for the unified-snippet footgun

If you have both apex.js (the web snippet) and the Capacitor plugin loaded, events only get native context (IDFA, install referrer, deep link URL) when the plugin is initialized. If the Integrations page shows "Capacitor plugin not detected" despite apex.js being active, install + initialize the plugin.

Verify with test mode

Call Apex.setTestMode({ enabled: true }) and fire a few events — they'll appear in the Debug Event Stream immediately, separate from production analytics. Disable test mode once verified.

Next Steps

Developer Account Setup

Ship the plugin to production only after completing the account setup for each platform you target.

Warning

These are owner-level tasks — they require an Apple Developer account ($99/year) and a Google Play Developer account ($25 one-time). Plan for a few hours of console clicks per platform.

iOS

  • Apple Developer Team ID (10-character alphanumeric)
  • Bundle ID registered in App Store Connect
  • APNS auth key (.p8 file) — required for both silent-push uninstall detection AND user-facing push notifications. The Push Notifications setup wizard walks you through generating it and verifying it works
  • SKAdNetwork schema URL registered in your Info.plist
  • Universal Links AASA file hosted — Apex auto-hosts this for you (see Deep Linking)

Send push notifications from Apex

Once the plugin is installed and your app is registering for remote notifications, you can send pushes from Apex without touching APNs directly:

  1. Open the Push Notifications setup wizard under Mobile Apps settings.
  2. Step 1 — generate an APNs auth key in the Apple Developer portal (5 minutes).
  3. Step 2 — upload the .p8 and enter your Team ID + Key ID + Bundle ID. Apex validates the key by signing a test JWT before storing it in AWS Secrets Manager (encrypted, per-project, never returned through any GET endpoint).
  4. Step 3 — send a test push to a registered device. The notification arrives on your phone within 1-2 seconds, and you'll know your project is wired up end-to-end.

After setup, the same credentials power the silent-push uninstall sweep (Phase 1d) and any user-facing pushes the communications pipeline sends. You can re-run the wizard at any time to rotate keys or test against a fresh device.

Android

  • Google Play Developer account with package name registered
  • SHA-256 signing certificate fingerprint — required for App Links verification
  • FCM server key — required for silent-push uninstall detection
  • adb shell pm get-app-links <package> after install to verify App Links are recognized
  • Meta: create an App Events Dataset in Meta Business Manager, generate an access token. Enables Meta Conversions API for mobile.
  • Google Ads: create an Offline Conversion Import action, connect via OAuth. Enables Google Ads Smart Bidding on mobile installs.

Once those are provisioned, configure them under Settings → Mobile and Apex takes over attribution reporting back to the networks automatically.