> ## 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.

# Event Properties

> Add structured, typed data to your events

Event properties allow you to add structured, typed data to your events. Properties must match your dashboard schema exactly, or the event will be rejected.

<CardGroup cols={3}>
  <Card title="Basic Usage" href="#creating-event-properties" icon="code" />

  <Card title="Enrichment" href="#event-enrichment" icon="sparkles" />

  <Card title="Common Patterns" href="#common-patterns" icon="layer-group" />
</CardGroup>

## Supported Types

EventProperties can contain the following types:

| Type              | Kotlin/Java Type  | Example                    |
| ----------------- | ----------------- | -------------------------- |
| **Boolean**       | `Boolean`         | `true`, `false`            |
| **Integer**       | `Int`, `Long`     | `42`, `1000L`              |
| **String**        | `String`          | `"Technology"`             |
| **Float**         | `Float`, `Double` | `99.99`, `3.14f`           |
| **DateTime**      | `java.util.Date`  | `Date()`                   |
| **Nested Object** | `EventProperties` | Nested properties          |
| **List**          | `List<T>`         | List of any supported type |

### Nullable Values

The API accepts nullable types. **Properties with `null` values will be automatically filtered** and not sent with the event.

```kotlin theme={"dark"}
EventProperties.from(
    "optional_field" to null  // This will be filtered out automatically
)
```

***

## Creating Event Properties

<CodeGroup>
  ```kotlin Kotlin theme={"dark"}
  import com.permutive.android.EventProperties

  val properties = EventProperties.from(
      "article_id" to 12345,
      "title" to "Breaking News",
      "category" to "Technology",
      "price" to 9.99,
      "is_premium" to true,
      "published_at" to Date(),
      "tags" to listOf("tech", "mobile", "android")
  )
  ```

  ```java Java theme={"dark"}
  import com.permutive.android.EventProperties;

  EventProperties properties = new EventProperties.Builder()
      .with("article_id", 12345)
      .with("title", "Breaking News")
      .with("category", "Technology")
      .with("price", 9.99)
      .with("is_premium", true)
      .with("published_at", new Date())
      .withStrings("tags", Arrays.asList("tech", "mobile", "android"))
      .build();
  ```
</CodeGroup>

***

## Nested Properties

Use nested EventProperties to represent hierarchical data structures:

<CodeGroup>
  ```kotlin Kotlin theme={"dark"}
  val properties = EventProperties.from(
      "article_id" to 12345,
      "user" to EventProperties.from(
          "type" to "premium",        // user.type
          "premium" to true,           // user.premium
          "subscription_tier" to "gold" // user.subscription_tier
      ),
      "metadata" to EventProperties.from(
          "source" to "mobile_app",
          "version" to "2.1.0"
      )
  )
  ```

  ```java Java theme={"dark"}
  EventProperties userProps = new EventProperties.Builder()
      .with("type", "premium")
      .with("premium", true)
      .with("subscription_tier", "gold")
      .build();

  EventProperties metadataProps = new EventProperties.Builder()
      .with("source", "mobile_app")
      .with("version", "2.1.0")
      .build();

  EventProperties properties = new EventProperties.Builder()
      .with("article_id", 12345)
      .with("user", userProps)
      .with("metadata", metadataProps)
      .build();
  ```
</CodeGroup>

***

## Complete Example

Here's a complete example matching a typical Pageview event schema:

### Schema Definition

| Name          | Type           |
| ------------- | -------------- |
| id            | Long           |
| description   | String         |
| tags          | List of String |
| published\_at | DateTime       |
| user.type     | String         |
| user.premium  | Boolean        |

<CodeGroup>
  ```kotlin Kotlin theme={"dark"}
  private fun pageProperties(
      id: Long,
      description: String,
      tags: List<String>,
      published: Date,
      userType: String,
      userIsPremium: Boolean
  ): EventProperties =
      EventProperties.from(
          "isp_info" to EventProperties.ISP_INFO,
          "geo_info" to EventProperties.GEO_INFO,
          "id" to id,
          "description" to description,
          "tags" to tags,
          "published_at" to published,
          "user" to EventProperties.from(
              "type" to userType,      // user.type
              "premium" to userIsPremium // user.premium
          )
      )

  // Usage
  val properties = pageProperties(
      id = 12345L,
      description = "Article about Android development",
      tags = listOf("android", "mobile", "development"),
      published = Date(),
      userType = "subscriber",
      userIsPremium = true
  )

  pageTracker = permutive.trackPage(
      title = "Article Title",
      url = Uri.parse("https://example.com/article"),
      eventProperties = properties
  )
  ```

  ```java Java theme={"dark"}
  private EventProperties pageProperties(
      Long id,
      String description,
      List<String> tags,
      Date published,
      String userType,
      Boolean userIsPremium
  ) {
      return new EventProperties.Builder()
          .with("isp_info", EventProperties.getISP_INFO())
          .with("geo_info", EventProperties.getGEO_INFO())
          .with("id", id)
          .with("description", description)
          .withStrings("tags", tags)
          .with("published_at", published)
          .with("user", new EventProperties.Builder()
              .with("type", userType)      // user.type
              .with("premium", userIsPremium) // user.premium
              .build()
          )
          .build();
  }

  // Usage
  EventProperties properties = pageProperties(
      12345L,
      "Article about Android development",
      Arrays.asList("android", "mobile", "development"),
      new Date(),
      "subscriber",
      true
  );

  PageTracker pageTracker = permutive.trackPage(
      properties,
      "Article Title",
      Uri.parse("https://example.com/article"),
      null
  );
  ```
</CodeGroup>

***

## Event Enrichment

Events can be enriched with additional information automatically by using special constants.

### Location and ISP Enrichment

Add location and ISP data to events using these constants:

```kotlin theme={"dark"}
EventProperties.from(
    "isp_info" to EventProperties.ISP_INFO,        // ISP information
    "geo_info" to EventProperties.GEO_INFO,        // Geographic location
    "ip_address" to EventProperties.IP_ADDRESS_HASH // Hashed IP address
)
```

This enriches events with:

* **ISP\_INFO**: Internet Service Provider details
* **GEO\_INFO**: Geographic location (country, region, city)
* **IP\_ADDRESS\_HASH**: Hashed IP address for privacy

Contact [Technical Services](mailto:technical-services@permutive.com) for configuration details.

### Watson NLP Enrichment

Add IBM Watson Natural Language Understanding data:

```kotlin theme={"dark"}
EventProperties.from(
    "watson_concepts" to EventProperties.ALCHEMY_CONCEPTS,
    "watson_entities" to EventProperties.ALCHEMY_ENTITIES,
    "watson_keywords" to EventProperties.ALCHEMY_KEYWORDS,
    "watson_taxonomy" to EventProperties.ALCHEMY_TAXONOMY,
    "watson_emotion" to EventProperties.ALCHEMY_DOCUMENT_EMOTION,
    "watson_sentiment" to EventProperties.ALCHEMY_DOCUMENT_SENTIMENT,
    "watson_taxonomy_labels" to EventProperties.ALCHEMY_TAXONOMY_LABELS,
    "watson_entity_names" to EventProperties.ALCHEMY_ENTITY_NAMES
)
```

See [IBM Watson Integration](/integrations/contextual/ibm-watson) for details.

### Complete Enrichment Example

<CodeGroup>
  ```kotlin Kotlin theme={"dark"}
  pageTracker = permutive.trackPage(
      eventProperties = EventProperties.from(
          "isp_info" to EventProperties.ISP_INFO,
          "geo_info" to EventProperties.GEO_INFO,
          "ip_address" to EventProperties.IP_ADDRESS_HASH,
          "article_id" to 12345,
          "category" to "technology"
      ),
      title = "Tech Article",
      url = Uri.parse("https://www.example.com/article"),
      referrer = Uri.parse("https://www.example.com/home")
  )
  ```

  ```java Java theme={"dark"}
  pageTracker = permutive.trackPage(
      new EventProperties.Builder()
          .with("isp_info", EventProperties.getISP_INFO())
          .with("geo_info", EventProperties.getGEO_INFO())
          .with("ip_address", EventProperties.getIP_ADDRESS_HASH())
          .with("article_id", 12345)
          .with("category", "technology")
          .build(),
      "Tech Article",
      Uri.parse("https://www.example.com/article"),
      Uri.parse("https://www.example.com/home")
  );
  ```
</CodeGroup>

***

## Type-Specific Methods (Java)

When building properties in Java, use type-specific methods for lists:

```java theme={"dark"}
EventProperties properties = new EventProperties.Builder()
    .withStrings("tags", Arrays.asList("tech", "mobile"))     // List<String>
    .withIntegers("scores", Arrays.asList(1, 2, 3))           // List<Integer>
    .withLongs("ids", Arrays.asList(100L, 200L))              // List<Long>
    .withBooleans("flags", Arrays.asList(true, false))        // List<Boolean>
    .withDoubles("prices", Arrays.asList(9.99, 19.99))        // List<Double>
    .build();
```

***

## Common Patterns

<AccordionGroup>
  <Accordion title="E-Commerce Properties" icon="cart-shopping">
    ```kotlin theme={"dark"}
    val purchaseProperties = EventProperties.from(
        "order_id" to "ORD-12345",
        "total_amount" to 149.99,
        "currency" to "USD",
        "item_count" to 3,
        "items" to listOf(
            EventProperties.from(
                "product_id" to "PROD-001",
                "name" to "Widget",
                "price" to 49.99,
                "quantity" to 1
            ),
            EventProperties.from(
                "product_id" to "PROD-002",
                "name" to "Gadget",
                "price" to 99.99,
                "quantity" to 2
            )
        ),
        "payment_method" to "credit_card",
        "shipping_method" to "express"
    )
    ```
  </Accordion>

  <Accordion title="Content Properties" icon="newspaper">
    ```kotlin theme={"dark"}
    val contentProperties = EventProperties.from(
        "article_id" to 12345,
        "title" to "Article Title",
        "author" to "John Doe",
        "category" to "Technology",
        "subcategories" to listOf("Mobile", "Android"),
        "word_count" to 1500,
        "published_at" to Date(),
        "is_premium" to true,
        "tags" to listOf("android", "sdk", "mobile"),
        "isp_info" to EventProperties.ISP_INFO,
        "geo_info" to EventProperties.GEO_INFO
    )
    ```
  </Accordion>

  <Accordion title="User Context Properties" icon="user">
    ```kotlin theme={"dark"}
    val userContextProperties = EventProperties.from(
        "user" to EventProperties.from(
            "id" to "user_12345",
            "type" to "premium",
            "subscription_tier" to "gold",
            "is_logged_in" to true,
            "account_age_days" to 365
        ),
        "session" to EventProperties.from(
            "id" to "session_abc123",
            "duration_seconds" to 120,
            "page_views" to 5
        )
    )
    ```
  </Accordion>
</AccordionGroup>

***

## Validation and Errors

### Schema Validation

Properties are validated against your event schema in the Permutive dashboard:

**✅ Valid:**

* Property names match exactly (case-sensitive)
* Property types match schema
* All required properties included

**❌ Invalid:**

* Misspelled property names
* Wrong property types
* Missing required properties

### Common Validation Errors

**Problem:** Event rejected with "Schema validation failed"

**Causes:**

1. Property name doesn't match dashboard (case-sensitive)
2. Property type doesn't match schema
3. Required property missing

**Solutions:**

1. Verify property names in dashboard
2. Check property types match
3. Include all required properties

**Example of incorrect types:**

```kotlin theme={"dark"}
// ❌ WRONG - Sending string where number expected
EventProperties.from(
    "article_id" to "12345"  // Schema expects Long, got String
)

// ✅ CORRECT
EventProperties.from(
    "article_id" to 12345L   // Matches schema
)
```

***

## Best Practices

<Tabs>
  <Tab title="Do">
    * Match property names and types exactly with your schema
    * Use enrichment constants when available
    * Create reusable property builder functions
    * Use nested properties for related data
    * Include relevant context properties
    * Validate against your schema before deploying
  </Tab>

  <Tab title="Don't">
    * Include PII (Personally Identifiable Information) without hashing
    * Use arbitrary property names not in your schema
    * Send null for required properties
    * Mix up property types
    * Create overly complex nested structures
  </Tab>
</Tabs>

<Warning>
  **Never send unhashed PII:**

  ```kotlin theme={"dark"}
  // ❌ WRONG - Sending raw email
  EventProperties.from("email" to "user@example.com")

  // ✅ CORRECT - Hash before sending
  EventProperties.from("email_sha256" to hashSHA256("user@example.com"))
  ```
</Warning>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Properties not appearing in dashboard">
    **Solutions:**

    1. Check property names match schema exactly
    2. Verify property types are correct
    3. Ensure event is being accepted (check logs)
    4. Confirm properties are defined in dashboard schema
  </Accordion>

  <Accordion title="Type conversion errors / App crashes">
    **Cause:** Incompatible type passed to builder.

    **Solution:** Ensure types match:

    ```kotlin theme={"dark"}
    // ❌ WRONG
    EventProperties.from("count" to "10")  // String instead of number

    // ✅ CORRECT
    EventProperties.from("count" to 10)    // Number
    ```
  </Accordion>

  <Accordion title="Nested properties not recognized">
    **Solution:** Ensure nested properties are defined in your dashboard schema:

    ```
    user.type
    user.premium
    user.subscription_tier
    ```
  </Accordion>
</AccordionGroup>

## Related Documentation

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

  <Card title="Event Tracking" icon="bolt" href="/sdks/mobile/android/features/event-tracking">
    Using properties with EventTracker
  </Card>

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

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

***

## API Reference

For complete API documentation, see the [Javadocs](https://sdk-docs.permutive.com/index.html).

### EventProperties Class

**Kotlin:**

* `EventProperties.from(vararg pairs: Pair<String, Any?>)` - Create from pairs

**Java:**

* `EventProperties.Builder()` - Create builder
* `builder.with(key: String, value: Any)` - Add property
* `builder.withStrings(key: String, values: List<String>)` - Add string list
* `builder.withIntegers(key: String, values: List<Int>)` - Add integer list
* `builder.withLongs(key: String, values: List<Long>)` - Add long list
* `builder.withBooleans(key: String, values: List<Boolean>)` - Add boolean list
* `builder.withDoubles(key: String, values: List<Double>)` - Add double list
* `builder.build()` - Build EventProperties

### Enrichment Constants

* `EventProperties.ISP_INFO` - ISP enrichment
* `EventProperties.GEO_INFO` - Geographic enrichment
* `EventProperties.IP_ADDRESS_HASH` - IP address hash
* `EventProperties.ALCHEMY_*` - Watson NLP enrichment constants
