# Android SDK

# Intempt Android SDK API Documentation

## Overview

Intempt Android SDK is a Kotlin SDK for tracking user events, managing user identification, and handling consent management in Android applications. This document describes all public methods available in the `Intempt` object.

## Initialization

### `initialize(context: Context)`

Initializes the Intempt SDK with the application context. This method must be called before using any other SDK methods, typically in your `Application` class's `onCreate()` method.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `context` | `Context` | Yes | Application context |

**Example:**
```kotlin
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Intempt.initialize(this)
    }
}
```

**Configuration:**

The SDK requires a configuration file `intempt-config.json` in your `assets` folder with the following structure:

```json
{
    "auth": {
        "INTEMPT_API_KEY": "username.password",
        "INTEMPT_SOURCE_ID": "your-source-id",
        "INTEMPT_ORGANIZATION_ID": "your-organization-id",
        "INTEMPT_PROJECT_ID": "your-project-id"
    },
    "options": {
        "isLoggingEnabled": false,
        "isTouchEnabled": true,
        "isTextCaptureEnabled": true,
        "isQueueEnabled": true,
        "isAutoCaptureEnabled": true,
        "itemsInQueue": 5,
        "timeBuffer": 5000
    }
}
```

**Configuration Options:**

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `isLoggingEnabled` | `Boolean` | `false` | Enable SDK logging |
| `isTouchEnabled` | `Boolean` | `true` | Enable automatic touch event tracking |
| `isTextCaptureEnabled` | `Boolean` | `true` | Enable automatic text capture |
| `isQueueEnabled` | `Boolean` | `true` | Enable event queuing |
| `isAutoCaptureEnabled` | `Boolean` | `true` | Enable automatic event capture |
| `itemsInQueue` | `Int` | `5` | Number of events to queue before sending |
| `timeBuffer` | `Long` | `5000` | Time buffer in milliseconds for event batching |

**Note:** If initialization fails, an error message will be printed to the console, but the app will continue to run.

---

## User Tracking Control Methods

### `Tracking.start()`

Enables tracking for the current user.

**Returns:** `void`

**Example:**
```kotlin
Intempt.Tracking.start()
```

---

### `Tracking.stop()`

Disables tracking for the current user.

**Returns:** `void`

**Example:**
```kotlin
Intempt.Tracking.stop()
```

---

### `Tracking.isTrackingEnabled()`

Checks if the user has opted in to tracking.

**Returns:** `Boolean` - `true` if tracking is enabled, `false` otherwise

**Example:**
```kotlin
if (Intempt.Tracking.isTrackingEnabled()) {
    // User has consented to tracking
    Intempt.track("Button Click", mapOf("button" to "signup"))
}
```

---

## Logging Control Methods

### `Logging.start()`

Enables SDK logging.

**Returns:** `void`

**Example:**
```kotlin
Intempt.Logging.start()
```

---

### `Logging.stop()`

Disables SDK logging.

**Returns:** `void`

**Example:**
```kotlin
Intempt.Logging.stop()
```

---

### `Logging.isLoggingEnabled()`

Checks if logging is currently enabled.

**Returns:** `Boolean` - `true` if logging is enabled, `false` otherwise

**Example:**
```kotlin
if (Intempt.Logging.isLoggingEnabled()) {
    println("SDK logging is active")
}
```

---

## User Identification Methods

### `identify(userId: String, eventTitle: String? = null, userAttributes: Map<String, String>? = null, data: Map<String, String>? = null)`

Identifies a user and associates them with a user ID. This method is used to link user actions to a specific user identity.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `userId` | `String` | Yes | Unique identifier for the user |
| `eventTitle` | `String?` | No | Custom event title (default: "Identify") |
| `userAttributes` | `Map<String, String>?` | No | User attributes map (requires `eventTitle` if provided) |
| `data` | `Map<String, String>?` | No | Additional event data |

**Returns:** `void`

**Validation:**
- `userId` must not be empty
- If `userAttributes` is provided, `eventTitle` must also be provided
- Forbidden event titles: `"auto-track"`, `"view page"`, `"leave page"`, `"change on"`, `"click on"`, `"submit on"`, `"identify"`, `"consent"`

**Example:**
```kotlin
Intempt.identify(
    userId = "user123",
    eventTitle = "User Registration",
    userAttributes = mapOf(
        "email" to "user@example.com",
        "name" to "John Doe",
        "plan" to "premium"
    ),
    data = mapOf(
        "registrationSource" to "website",
        "referrer" to "google"
    )
)
```

---

### `alias(userId: String, anotherUserId: String)`

Creates an alias between two user IDs. Used when a user is identified with different IDs (e.g., anonymous ID and authenticated ID).

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `userId` | `String` | Yes | Primary user ID |
| `anotherUserId` | `String` | Yes | Secondary user ID to alias |

**Returns:** `void`

**Example:**
```kotlin
Intempt.alias(
    userId = "anonymous_123",
    anotherUserId = "authenticated_user456"
)
```

---

## Group/Account Methods

### `group(accountId: String, eventTitle: String? = null, accountAttributes: Map<String, String>? = null)`

Associates a user with a group or account.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `accountId` | `String` | Yes | Unique identifier for the account/group |
| `eventTitle` | `String?` | No | Custom event title (default: "Identify") |
| `accountAttributes` | `Map<String, String>?` | No | Account attributes map (requires `eventTitle` if provided) |

**Returns:** `void`

**Validation:**
- `accountId` must not be empty
- If `accountAttributes` is provided, `eventTitle` must also be provided
- Forbidden event titles: same as `identify` method

**Example:**
```kotlin
Intempt.group(
    accountId = "company_abc",
    eventTitle = "Account Created",
    accountAttributes = mapOf(
        "name" to "Acme Corp",
        "plan" to "enterprise",
        "employees" to "500"
    )
)
```

---

## Event Tracking Methods

### `track(eventTitle: String, data: Map<String, String>)`

Tracks a custom event with associated data.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `eventTitle` | `String` | Yes | Name of the event |
| `data` | `Map<String, String>` | Yes | Event data map (must not be empty) |

**Returns:** `void`

**Validation:**
- `eventTitle` is required and must not be empty
- `data` must be provided and non-empty
- Forbidden event titles: same as `identify` method

**Example:**
```kotlin
Intempt.track(
    eventTitle = "Purchase Completed",
    data = mapOf(
        "orderId" to "order_123",
        "amount" to "99.99",
        "currency" to "USD"
    )
)
```

---

### `record(eventTitle: String, accountId: String? = null, userId: String? = null, accountAttributes: Map<String, String>? = null, userAttributes: Map<String, String>? = null, data: Map<String, String>? = null)`

Records an event with optional user and account information.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `eventTitle` | `String` | Yes | Name of the event |
| `accountId` | `String?` | No | Account identifier |
| `userId` | `String?` | No | User identifier |
| `accountAttributes` | `Map<String, String>?` | No | Account attributes |
| `userAttributes` | `Map<String, String>?` | No | User attributes |
| `data` | `Map<String, String>?` | No | Additional event data |

**Returns:** `void`

**Validation:**
- `eventTitle` is required
- Forbidden event titles: same as `identify` method

**Example:**
```kotlin
Intempt.record(
    eventTitle = "Feature Used",
    userId = "user123",
    accountId = "account456",
    data = mapOf(
        "feature" to "analytics_dashboard",
        "duration" to "300"
    ),
    userAttributes = mapOf(
        "role" to "admin"
    ),
    accountAttributes = mapOf(
        "plan" to "enterprise"
    )
)
```

---

## Consent Management

### `consent(action: String, validUntil: Long, email: String? = null, message: String? = null, category: String? = null)`

Records user consent preferences.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `action` | `String` | Yes | Consent action (`"accept"` or `"reject"`) |
| `validUntil` | `Long` | Yes | Timestamp when consent expires (Unix timestamp in milliseconds) |
| `email` | `String?` | No | User email address |
| `message` | `String?` | No | Consent message |
| `category` | `String?` | No | Consent category |

**Returns:** `void`

**Validation:**
- `action` must be either `"accept"` or `"reject"`
- `validUntil` is required (Unix timestamp in milliseconds)

**Example:**
```kotlin
Intempt.consent(
    action = "accept",
    validUntil = System.currentTimeMillis() + (365 * 24 * 60 * 60 * 1000L), // 1 year from now
    email = "user@example.com",
    category = "analytics"
)
```

---

## Product Tracking Methods

### `productAdd(productId: String, quantity: Int)`

Tracks when a product is added to cart.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `productId` | `String` | Yes | Product identifier |
| `quantity` | `Int` | Yes | Quantity added |

**Returns:** `void`

**Example:**
```kotlin
Intempt.productAdd(
    productId = "prod_123",
    quantity = 2
)
```

**Event Title:** `"Added to cart"`

---

### `productOrdered(products: List<Map<String, Any>>)`

Tracks when products are ordered (purchased).

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `products` | `List<Map<String, Any>>` | Yes | List of product maps, each containing `productId` (String) and `quantity` (Int) |

**Returns:** `void`

**Validation:**
- Each product map must contain:
  - `productId`: String (required, non-empty)
  - `quantity`: Int (required, must be > 0)

**Example:**
```kotlin
Intempt.productOrdered(
    products = listOf(
        mapOf("productId" to "prod_123", "quantity" to 2),
        mapOf("productId" to "prod_456", "quantity" to 1)
    )
)
```

**Event Title:** `"Product ordered"`

---

### `productView(productId: String)`

Tracks when a product is viewed.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `productId` | `String` | Yes | Product identifier |

**Returns:** `void`

**Example:**
```kotlin
Intempt.productView("prod_123")
```

**Event Title:** `"Product viewed"`

---

## Session Management

### `logOut()`

Handles user logout by clearing session data and refreshing the auto tracker.

**Returns:** `void`

**Example:**
```kotlin
Intempt.logOut()
```

**Note:** This method only executes if the user has opted in to tracking. The profile ID is preserved after logout.

---

## Recommendation API

### `recommendation(id: String, quantity: Int, fields: List<String>, productId: String?): JsonObject?`

Fetches product recommendations from the Intempt API. This is a suspend function and must be called from a coroutine.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | `String` | Yes | Feed ID for recommendations |
| `quantity` | `Int` | Yes | Number of recommendations to return |
| `fields` | `List<String>` | Yes | Fields to include in the response |
| `productId` | `String?` | No | Optional product ID for context |

**Returns:** `JsonObject?` - Recommendation data or `null` on error

**Example:**
```kotlin
lifecycleScope.launch {
    val recommendations = Intempt.recommendation(
        id = "123",
        quantity = 10,
        fields = listOf("productId", "name", "price", "image"),
        productId = "prod_123"
    )
    
    recommendations?.let {
        // Process recommendations
        println("Recommended products: $it")
    }
}
```

**API Details:**
- **Endpoint:** `{api}/{organization}/projects/{project}/feeds/{id}/data`
- **Method:** POST
- **Authentication:** Basic Auth (derived from API key in config)

**Error Handling:**
- Returns `null` if the request fails
- Errors are logged if logging is enabled

---

## Experiments and Personalization

### `experiment: ModificationProvider`

Provides access to server-side experiments. Use this to fetch experiment variations.

**Methods:**

#### `getByGroup(data: List<String>): JsonElement?` (suspend)

Fetches experiments by group names.

**Example:**
```kotlin
lifecycleScope.launch {
    val experiments = Intempt.experiment.getByGroup(
        listOf("header", "footer", "sidebar")
    )
    experiments?.let {
        // Apply experiment variations
    }
}
```

#### `getByName(data: List<String>): JsonElement?` (suspend)

Fetches experiments by experiment names.

**Example:**
```kotlin
lifecycleScope.launch {
    val experiments = Intempt.experiment.getByName(
        listOf("homepage_variant_a", "checkout_variant_b")
    )
    experiments?.let {
        // Apply experiment variations
    }
}
```

#### `getByGroupAsync(data: List<String>): CompletableFuture<JsonElement?>`

Asynchronous version of `getByGroup` for Java interop.

#### `getByNameAsync(data: List<String>): CompletableFuture<JsonElement?>`

Asynchronous version of `getByName` for Java interop.

---

### `personalization: ModificationProvider`

Provides access to server-side personalization campaigns. Use this to fetch personalized content.

**Methods:**

Same as `experiment` - `getByGroup`, `getByName`, `getByGroupAsync`, `getByNameAsync`.

**Example:**
```kotlin
lifecycleScope.launch {
    val personalizations = Intempt.personalization.getByGroup(
        listOf("banner", "promo_section")
    )
    personalizations?.let {
        // Apply personalized content
    }
}
```

---

## Privacy and Data Capture

### `doNotCaptureText(view: View)`

Marks a view to exclude its text content from automatic capture. This is useful for sensitive data like passwords or personal information.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `view` | `View` | Yes | View to exclude from text capture |

**Returns:** `void`

**Supported View Types:**
- `EditText`
- `Spinner`
- `ToggleButton`
- `CheckBox`
- `RadioButton`
- `CompoundButton`
- `TextView`
- `SeekBar`
- `RatingBar`
- `TimePicker`
- `DatePicker`
- `ListView`

**Example:**
```kotlin
val passwordField = findViewById<EditText>(R.id.password)
Intempt.doNotCaptureText(passwordField)
```

**Note:** If an unsupported view type is passed, an error will be logged.

---

## Common Behavior

### Opt-In Requirement

Most tracking methods (`identify`, `group`, `track`, `record`, `alias`, `consent`, `productAdd`, `productOrdered`, `productView`, `logOut`) will silently return without executing if the user has opted out of tracking. Use `Tracking.isTrackingEnabled()` to check the current status.

### Automatic IDs

The following IDs are automatically included in all tracking events:
- `profileId`: Generated/retrieved from storage
- `sessionId`: Current session identifier
- `pageId`: Current page identifier

### Automatic Event Capture

The SDK automatically captures:
- Screen views (Activity lifecycle events)
- Touch events (clicks, taps)
- Form changes (text input changes)
- Fragment transitions
- App install/upgrade events
- Session start events

This behavior can be controlled via configuration options in `intempt-config.json`.

### Forbidden Event Titles

The following event titles are forbidden and will cause validation errors:
- `"auto-track"`
- `"view page"`
- `"leave page"`
- `"change on"`
- `"click on"`
- `"submit on"`
- `"identify"`
- `"consent"`

---

## Error Handling

All validation errors are logged using the SDK's logging system. Common errors include:

- **Configuration errors:** Missing or invalid configuration file
- **Parameter validation errors:** Missing required parameters or invalid values
- **Field-specific errors:** Specific field validation failures
- **Forbidden event titles:** Attempting to use reserved event titles

Errors are logged but do not throw exceptions, allowing your app to continue running. Enable logging with `Intempt.Logging.start()` to see error messages.

---

## Best Practices

1. **Initialize early:** Call `Intempt.initialize()` in your `Application.onCreate()` method before any other SDK calls.

2. **Check tracking status:** Before tracking, check if the user has opted in:
   ```kotlin
   if (Intempt.Tracking.isTrackingEnabled()) {
       Intempt.track("Action", mapOf("key" to "value"))
   }
   ```

3. **Use coroutines for async operations:** Methods like `recommendation()` and modification providers are suspend functions. Use coroutines:
   ```kotlin
   lifecycleScope.launch {
       val result = Intempt.recommendation(...)
   }
   ```

4. **Protect sensitive data:** Use `doNotCaptureText()` for views containing sensitive information like passwords or credit card numbers.

5. **Configure appropriately:** Set up your `intempt-config.json` file with appropriate options for your use case.

6. **Respect user consent:** Always respect user consent preferences and use the `consent()` method to record consent decisions.

7. **Handle null results:** Async methods like `recommendation()` and modification providers can return `null` on error. Always check for null before using results.

---

## Type Definitions

### Configuration File Structure

```json
{
    "auth": {
        "INTEMPT_API_KEY": "string",      // Format: "username.password"
        "INTEMPT_SOURCE_ID": "string",
        "INTEMPT_ORGANIZATION_ID": "string",
        "INTEMPT_PROJECT_ID": "string"
    },
    "options": {
        "isLoggingEnabled": boolean,
        "isTouchEnabled": boolean,
        "isTextCaptureEnabled": boolean,
        "isQueueEnabled": boolean,
        "isAutoCaptureEnabled": boolean,
        "itemsInQueue": number,
        "timeBuffer": number
    }
}
```

### ModificationProvider Interface

```kotlin
interface ModificationProvider {
    suspend fun getByGroup(data: List<String>): JsonElement?
    suspend fun getByName(data: List<String>): JsonElement?
    fun getByGroupAsync(data: List<String>): CompletableFuture<JsonElement?>
    fun getByNameAsync(data: List<String>): CompletableFuture<JsonElement?>
}
```

---

## Version Information

- **SDK Version:** See `BuildConfig.sdkVersion` in your build
- **Documentation Version:** 1.0.0
- **Last Updated:** 2024

---

## Additional Resources

- [Android SDK Documentation](https://docs.intempt.com/docs/android-sdk)
- [Intempt Platform](https://www.intempt.com)


