# User Identifier & Properties

{% hint style="info" %}
User Identifier Management

User Identifiers are used to uniquely identify users.\
For the meaning and importance of User Identifiers and guidelines on how to choose them, refer to the [Managing User Identifiers](/en/getting-started/user-identifier.md) documentation.
{% endhint %}

### Using User Identifiers You Manage

Because server-side SDKs cannot identify users on their own, you must **always pass the User Identifier directly as a parameter**.\
The identifier you pass can be a primary key you manage, a device identifier, a member ID, an email, a hash value, etc.

### Example

The following is an example of distributing a Variation and then sending a user event.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
import io.hackle.sdk.HackleClient
import io.hackle.sdk.Hackle
import io.hackle.sdk.common.Variation
import io.hackle.sdk.common.Event
import io.hackle.sdk.common.User

val user: User = Hackle.user("ae2182e0")

// Variation Distribution
val variation: Variation = hackleClient.variation(experimentKey, user)

// Send user event
hackleClient.track(event, user)
```

{% endtab %}

{% tab title="Java" %}

```java
import io.hackle.sdk.HackleClient
import io.hackle.sdk.common.Variation
import io.hackle.sdk.common.Event
import io.hackle.sdk.common.User

User user = User.of("ae2182e0");

// Variation Distribution
Variation variation = hackleClient.variation(experimentKey, user);

// Send user event
hackleClient.track(event, user);
```

{% endtab %}
{% endtabs %}

## Additional Identifiers

Additional identifiers beyond the default identifiers can be sent using the example code below.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
import io.hackle.sdk.Hackle
import io.hackle.sdk.common.User


val user = Hackle.user("ae2182e0") { // Default identifier
    userId("143")                    // User ID (Hackle ID compatible)
    deviceId("ae2182e0")             // Device ID (Hackle ID compatible)
    identifier("myCustomId", "42")   // Custom ID
}
```

{% endtab %}

{% tab title="Java" %}

```java
import io.hackle.sdk.common.User

User user = User.builder("ae2182e0") // Default identifier
    .userId("143")                   // User ID (Hackle ID compatible)
    .deviceId("ae2182e0")            // Device ID (Hackle ID compatible)
    .identifier("myCustomId", "42")  // Custom ID
    .build()
```

{% endtab %}
{% endtabs %}

## Property

The Hackle SDK supports adding properties to a User object.

* A property must be sent as a key-value pair consisting of a Property Key and a Property Value.
* You can add a maximum of 128 properties per user object.

<table><thead><tr><th width="133.04296875">Category</th><th width="127.60546875">Type</th><th>Constraints</th></tr></thead><tbody><tr><td>Property Key</td><td><code>string</code></td><td><ul><li>Character limit is 128 characters.</li><li>Case-insensitive.</li><li>For example, AGE and age are recognized as the same Property Key.</li></ul></td></tr><tr><td>Property Value</td><td><code>boolean</code>, <code>string</code>, <code>number</code>, <code>array</code></td><td><ul><li>For string type, the character limit is 1024 characters.</li><li>String type is case-sensitive.</li><li>For example, APPLE and apple are recognized as different Property Values.</li><li>For number type, up to 15 integer digits and up to 6 decimal places are supported.</li></ul></td></tr></tbody></table>

### Example

The User object is used as a parameter in Variation Distribution, Feature Flag Decision, and user event tracking.\
In the example below, three properties (`age`, `grade`, `is_paying_user`) have been added.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
import io.hackle.sdk.HackleClient
import io.hackle.sdk.common.Variation
import io.hackle.sdk.common.Event
import io.hackle.sdk.common.User

val user: User = Hackle.user(userId) {
    property("age", 30)
    property("grade", "GOLD")
    property("is_paying_user", false)
}

// Variation Distribution
val variation: Variation = hackleClient.variation(experimentKey, user)

// Feature Flag Decision
val featureOn: Boolean = hackleClient.isFeatureOn(featureKey, user)

// Send user event
hackleClient.track(event, user)
```

{% endtab %}

{% tab title="Java" %}

```java
import io.hackle.sdk.HackleClient
import io.hackle.sdk.common.Variation
import io.hackle.sdk.common.Event
import io.hackle.sdk.common.User

User user = User.builder(userId)
    .property("age", 30)
    .property("grade", "GOLD")
    .property("is_paying_user", false)
    .build();

// Variation Distribution
Variation variation = hackleClient.variation(experimentKey, user);

// Feature Flag Decision
boolean featureOn = hackleClient.isFeatureOn(featureKey, user);

// Send user event
hackleClient.track(event, user);
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hackle.io/en/development-guide/java-kotlin/user-identifier.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
