> ## Documentation Index
> Fetch the complete documentation index at: https://docs.permutive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Verifying Your Integration

> Verify your Permutive Android SDK integration is working correctly

This guide shows you how to verify your Permutive Android SDK integration is working correctly by checking debug logs.

<Info>
  **Prerequisites:**

  * SDK installed and initialized
  * **adb** (Android Debug Bridge) installed on your computer
  * Device configured for developer mode
</Info>

## Enable Debug Logging

Debug logging is disabled by default. Enable it via ADB:

```bash theme={"dark"}
# Enable verbose logging
adb shell setprop log.tag.Permutive VERBOSE

# Start capturing logs
adb logcat -s Permutive
```

To disable later:

```bash theme={"dark"}
adb shell setprop log.tag.Permutive INFO
```

<Note>
  `setDeveloperMode(true)` does not currently surface these logs in the published SDK — the developer messages are logged at `DEBUG` priority, which Android suppresses unless the `log.tag.Permutive` system property is set. Use the ADB commands above.
</Note>

## Capture Logs In-App

From SDK v1.11.0 you can also capture SDK logs directly in your app, without adb. This is useful for surfacing logs in QA builds or forwarding SDK errors to your own logging or crash-reporting tools. Both APIs emit the log tag and message, filtered to a minimum [log level](https://developer.android.com/reference/android/util/Log#constants) (default: `Log.VERBOSE`).

<Tabs>
  <Tab title="Flow (Kotlin)">
    `logs()` returns a hot Flow that replays the 100 most recent messages to new collectors. Collect it from a lifecycle-aware scope so collection is cancelled when your component is destroyed:

    ```kotlin theme={"dark"}
    lifecycleScope.launch {
        permutive.logs(minLevel = Log.ERROR).collect { (tag, message) ->
            sendToCrashReporting("$tag: $message")
        }
    }
    ```
  </Tab>

  <Tab title="Listener (Kotlin/Java)">
    `setLogListener` invokes a callback for each new log message. Only one listener can be active at a time — calling it again replaces the previous listener, and passing `null` removes it.

    <CodeGroup>
      ```kotlin Kotlin theme={"dark"}
      permutive.setLogListener(minLevel = Log.WARN) { tag, message ->
          Log.w(tag, message)
      }

      // Remove the listener when done
      permutive.setLogListener(listener = null)
      ```

      ```java Java theme={"dark"}
      permutive.setLogListener(Log.WARN, (tag, message) ->
          Log.w(tag, message)
      );

      // Remove the listener when done
      permutive.setLogListener(Log.VERBOSE, null);
      ```
    </CodeGroup>

    <Warning>
      If your listener captures an Activity, Fragment, or other Android component, remove the listener when that component is destroyed to avoid memory leaks.
    </Warning>
  </Tab>
</Tabs>

## What to Verify

<Steps>
  <Step title="SDK Startup">
    When the SDK starts successfully, you should see:

    ```
    D/Permutive(15399): Starting Permutive v1.14.1
    D/Permutive(15399): Fetched configuration information
    ```

    <Check>
      This confirms SDK initialized successfully and credentials are correct.
    </Check>

    **If you see an error:**

    ```
    D/Permutive(15124): Error fetching configuration - please check that your workspace id & API key is correct
    ```

    Check your Workspace ID, API Key, and ensure Android is enabled for your workspace.
  </Step>

  <Step title="Identity Tracking">
    When identity is set, you should see:

    ```
    D/Permutive(15859): Identified user with aliases: aaid, default
    ```

    Common aliases:

    * **aaid** - Android Advertising ID (if using AaidAliasProvider)
    * **default** - Default anonymous ID
    * **user\_id** - Custom user ID
    * **email\_sha256** - Hashed email
  </Step>

  <Step title="Event Tracking">
    When events are tracked and accepted:

    ```
    D/Permutive(15859): Published events with names (Pageview, SegmentEntry) (Accepted: 4 / 4)
    ```

    <Check>
      All events accepted = Your integration is working correctly!
    </Check>

    **If events are rejected**, you'll see schema validation errors with details about what needs to be fixed.
  </Step>

  <Step title="Ad Targeting (if applicable)">
    When ads request targeting data:

    ```
    D/Permutive: Permutive reaction segments appended to Google Ad request: 123, 456, 789
    D/Permutive: Permutive contextual cohorts appended to Google Ad request: cabf, bzwu
    ```

    This confirms cohort IDs are being added to ad requests.
  </Step>
</Steps>

## PageTracker Lifecycle

If you're using the PageTracker API, verify this sequence in logs:

<AccordionGroup>
  <Accordion title="Page created" icon="play">
    Creating a PageTracker is not logged directly — look for the Pageview event being published shortly after:

    ```
    Published events with names (Pageview) (Accepted: 1 / 1)
    ```

    Custom events tracked against the page are logged as:

    ```
    Page event tracked (id: abc123)
    name: ArticleShared
    properties: {...}
    ```
  </Accordion>

  <Accordion title="Page paused" icon="pause">
    ```
    Page paused (id: abc123)
    ```

    Logged when `pageTracker.pause()` is called (typically in `onPause()`).
  </Accordion>

  <Accordion title="Page resumed" icon="play">
    ```
    Page resumed (id: abc123)
    ```

    Logged when `pageTracker.resume()` is called (typically in `onResume()`).
  </Accordion>

  <Accordion title="Page stopped" icon="stop">
    ```
    Page stopped (id: abc123)
    ```

    Logged when `pageTracker.close()` is called (typically in `onDestroy()`).
  </Accordion>

  <Accordion title="Percentage viewed updated" icon="percent">
    ```
    Page percentage viewed updated (id: abc123) to 75%
    ```

    Logged when `pageTracker.updatePercentageViewed()` is called.
  </Accordion>
</AccordionGroup>

## Schema Validation Errors

If events are rejected due to schema violations:

```
D/Permutive(16644): Error publishing event with name "Pageview":
D/Permutive(16644): Code: 1007
D/Permutive(16644): Status: BadRequest
D/Permutive(16644): Cause: Schema validation failed with reason(s):
  [#: extraneous key [publishingDate] is not permitted]
  [#/article/categories: expected type: JSONArray, found: String]
```

**How to fix:**

1. **Unknown property** - Remove property or add it to your schema in the dashboard
2. **Type mismatch** - Fix the property type in your code:

```kotlin theme={"dark"}
// Wrong - String instead of Array
EventProperties.from("categories" to "Technology")

// Correct - Array type
EventProperties.from("categories" to listOf("Technology", "Mobile"))
```

<Warning>
  Events with schema violations are **rejected by servers** and will not be processed. Always fix schema issues before releasing your app.
</Warning>

## Common Verification Issues

<AccordionGroup>
  <Accordion title="No logs appearing">
    **Solutions:**

    1. Verify logging is enabled: `adb shell setprop log.tag.Permutive VERBOSE`
    2. Check adb is connected: `adb devices`
    3. Restart logcat: `adb logcat -c` then `adb logcat -s Permutive`
    4. Verify SDK is initialized
  </Accordion>

  <Accordion title="Events not showing in dashboard">
    **Causes:**

    1. Dashboard requires time to process events (5-10 minutes)
    2. Event filtering in dashboard
    3. Date/time range in dashboard

    **Solutions:**

    1. Wait 10 minutes and refresh dashboard
    2. Check dashboard filters
    3. Verify date/time range includes now
  </Accordion>

  <Accordion title="Identity not persisting">
    **Causes:**

    1. Clearing app data between sessions
    2. Not setting identity on initialization
    3. Using test/emulator that resets

    **Solutions:**

    1. Don't clear app data during testing
    2. Set identity or use AAID provider at initialization
    3. Test on physical device
  </Accordion>
</AccordionGroup>

## Verification Checklist

Use this checklist to verify your integration:

### Basic Setup

* [ ] SDK starts successfully ("Starting Permutive v1.14.1")
* [ ] Configuration fetched without errors
* [ ] Workspace ID and API Key are correct

### Identity

* [ ] Identity log appears on first launch
* [ ] Correct aliases are shown
* [ ] Identity persists across app restarts

### Event Tracking

* [ ] Events are being published
* [ ] All events show "Accepted" (not rejected)
* [ ] No schema validation errors
* [ ] Correct event names (case-sensitive)

### PageTracker (if using)

* [ ] Pageview event published after `trackPage(...)`
* [ ] "Page paused" when activity pauses
* [ ] "Page resumed" when activity resumes
* [ ] "Page stopped" when activity destroyed

### Ad Targeting (if using)

* [ ] Segments appended to ad requests
* [ ] Targeting log appears when ads load

### Dashboard

* [ ] Events appearing in dashboard (may take a few minutes)
* [ ] User cohorts showing (after qualifying events)

## Next Steps

Once verification is complete:

1. Remove debug logging from production builds
2. Test all user flows that include tracking
3. Verify dashboard data after 24 hours of live usage
4. Monitor for errors in production logs

<CardGroup cols={2}>
  <Card title="Page Tracking" icon="file" href="/sdks/mobile/android/features/page-tracking">
    Learn about PageTracker lifecycle
  </Card>

  <Card title="Event Properties" icon="list" href="/sdks/mobile/android/core-concepts/event-properties">
    Property types and validation
  </Card>

  <Card title="Identity Management" icon="user" href="/sdks/mobile/android/core-concepts/identity-management">
    User identification
  </Card>

  <Card title="Issues" icon="wrench" href="/sdks/mobile/android/troubleshooting/common-errors">
    Solutions to common issues
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.