# Custom Properties

You can add your own custom properties for use in the conditional targeting system. Adding more data about your users/app can provide more powerful options for targeting and optimization.

### Well Known vs Custom Properties

There are two types of custom properties:

* Well known properties: A set of properties we define, and you set. These are common things that most apps have like "user\_signup\_date". By using this well known set, our optimization system can incorporate these properties (when provided) and make smarter optimization decisions. We suggest you set as many of these that make sense for your app's user experience.
* Custom properties can be any key/value pairs which you might find useful for targeting

### Well Known Property List

| Property Name           | Type              | Description                                                                                                                             |
| ----------------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| user\_signup\_date      | datetime (NSDate) | The timestamp of when this user signed up for your app/service.                                                                         |
| user\_signed\_in        | bool              | Is the user signed into an account                                                                                                      |
| have\_user\_email       | bool              | Do we have an email address tied to this user's account.                                                                                |
| user\_email\_validated  | bool              | Has the user validated their email, confirming they own it.                                                                             |
| have\_user\_phone       | bool              | Do we have phone number tied to this user's account.                                                                                    |
| user\_age               | int               | The user's exact age, in years. Use user\_approx\_age if you only know the approximate age of the user.                                 |
| user\_approx\_age       | int               | The user's approximate age, in years. Use user\_age if you know the exact age of the user.                                              |
| user\_pronouns          | string            | The user's preferred pronouns. Example: she\_her, he\_him, they\_them, other, declined\_to\_say                                         |
| user\_gender            | string            | The user's gender. Examples: male, female, nonbinary, declined\_to\_say.                                                                |
| user\_inferred\_gender  | string            | The user's gender, if inferred and not user specified.                                                                                  |
| has\_paid\_subscription | bool              | Does this user have a paid subscription.                                                                                                |
| ever\_subscribed        | bool              | True if the user has ever been a paid subscriber, even if they no longer currently subscribe.                                           |
| has\_purchased          | bool              | Has the user ever made a purchase.                                                                                                      |
| purchase\_count         | int               | Count of all purchases made.                                                                                                            |
| total\_purchase\_value  | float             | Total purchase value (excluding subscriptions), this user had made. Unit/currency is up to you, but should be consistent for all users. |
| referral\_source        | string            | The name of how this user was referred to your app (fb\_ad, google\_ad, organic, search, user\_referral, etc).                          |
| referral\_id            | string            | An ID relating to the referral source (example: campaign ID)                                                                            |
| user\_was\_referred     | bool              | Was this user referred by another user?                                                                                                 |
| user\_referral\_count   | int               | How many users has this user referred.                                                                                                  |
| session\_source         | string            | How did the user launch the app for this app session? Examples: deeplink, notification, manual\_launch, email\_link, web\_link, etc.    |

## Setting Properties in Code

You can set properties in code using the following functions of the `CriticalMoments.sharedInstance` object.

{% hint style="info" %}
Ideally set properties before calling `start` on CriticalMoments. Some events like `app_start` occur very early, and you'll want properties to be available.&#x20;

If your properties are async, consider firing an `app_loaded` event after setting them, which you can use as a trigger for conditions requiring them.
{% endhint %}

{% tabs %}
{% tab title="Swift Example" %}

```swift
// Optionally try/catch for errors
let cm = CriticalMoments.sharedInstance()
try? cm.setBoolProperty(true, forKey: "has_pro_account")
try? cm.setIntegerProperty(42, forKey: "max_game_level")
try? cm.setStringProperty("creator", forKey: "user_persona")
try? cm.setFloatProperty(42.42, forKey: "total_spending")
try? cm.setTimeProperty(Date.now, forKey: "account_upgrade_timestamp")
```

{% endtab %}

{% tab title="Objective-C Example" %}

```objectivec
# Optionally check return `success` value and error
CriticalMoments* cm = CriticalMoments.sharedInstance;
[cm setBoolProperty:true forKey:@"has_pro_account" error:nil];
[cm setIntegerProperty:42 forKey:@"max_game_level" error:nil];
[cm setStringProperty:@"creator" forKey:@"user_persona" error:nil];
[cm setFloatProperty:42.42 forKey:@"total_spending" error:nil];
[cm setTimeProperty:[NSDate now] forKey:@"account_upgrade_timestamp" error:nil];
```

{% endtab %}
{% endtabs %}

## Setting Many Properties via JSON

You can set a set of properties from JSON formatted data. This can be very helpful, allowing your to add properties to shipping clients without updating the app.

Properties must be set before calling `[CriticalMoments.sharedInstance start]`. Properties set after calling start will be ignored.

Generally this API is used like follows:

* You create a server endpoint (for example `/user_properties`), which is authenticated and retrieves information about this user in JSON format.
* Call this server API on launch, and then pass the resulting JSON to `registerPropertiesFromJson`
* Optionally cache this result for faster startup (used cache results on launch, refresh cache for next launch).

{% tabs %}
{% tab title="Swift Example" %}

```swift
let jsonData = """
{
  "bool_property": true,
  "int_property": 42,
  "float_property": 42.42,
  "string_property": "hello world"
}
""".data(using: .utf8)!

do {
    try CriticalMoments.sharedInstance().setPropertiesFromJson(jsonData)
} catch {
    print("JSON parsing error: \(error).")
}
```

{% endtab %}

{% tab title="Objective C Example" %}
{% code overflow="wrap" fullWidth="true" %}

```objectivec
NSData* jsonData = [@"\
{\
  \"bool_property\": true,\
  \"int_property\": 42,\
  \"float_property\": 42.42,\
  \"string_property\": \"hello world\"\
}" dataUsingEncoding:NSUTF8StringEncoding];

NSError* jsonError;
[CriticalMoments.sharedInstance registerPropertiesFromJson:jsonData error:&jsonError];
if (jsonError != nil) {
    NSLog(@"There was an issue with the JSON: %@", jsonError.localizedDescription);
}
```

{% endcode %}
{% endtab %}
{% endtabs %}
