Schema for objects and fields
Data in Optimizely Data Platform (ODP) is stored in collections called objects (also known as a database table). Objects are composed of fields. Identifiers are a specific type of field that identifies customers. Fields link objects together using relationships.
- Objects – Database tables that act as a collection of client data. Objects contain fields that are the names of the table columns. Objects are connected to other objects by relationships.
- Fields – Columns in a database table (an Object in Connect Platform for ODP). All objects have one primary key field that must be a string or number. Fields have one of the following data types: string, number, boolean, timestamp.
- string – Any printable UTF-8 character, including space. Text is limited to 1024 characters.
- number – Represented in standard decimal or integer format (for example: 0, 3.14159, -2.3, -0.112).
- boolean – Must be 0, 1, true, or false.
- timestamp – Must be ISO 8601 format or UNIX epoch (seconds since January 1, 1970). For example: 1435708800, 2015-07-01T00:00:00-00:00, 2015-07-01T12:30:00-07:00.
Note If time and timezone are not provided, the system assumes 12 a.m. UTC for the time.
- Identifiers – Special fields that identify customers. You can only create identifiers for the customer object. Learn more about identifiers in the ODP documentation.
- Relationships – 1:1 database table relationships.
For more information on viewing your existing default and custom objects and fields in ODP, see Review data fields.
Important You must prefix all objects and fields that are unique to your app with your app_id. For example, if your app_id is acme, prefix all of your objects and fields with acme.
An exception is fields within an object that your app creates. For example, if your app created an acme_tickets object, then you do not have to prefix fields within this object.
There are two ways of creating and updating ODP schema from your app:
- Static – Recommended as it is safer and easier to maintain. With static schema, when users install and upgrade your app, Connect Platform for ODP makes sure all objects and fields declared in the app's YAML files are created in the ODP account where the user is installing/upgrading the app.
- Dynamic – Useful when you need to create objects and fields dynamically based on user input.
Important Change ODP schema with caution. After you create an object or field, you cannot delete or rename it.
For more information about ODP data structure and schema, see the ODP developer documentation.
YAML file properties for defining objects and fields
The following table lists the properties and their descriptions for YAML files that define objects.
Property | Description |
|---|---|
`name` | The name of the object (should be plural). Must be globally unique. You must prefix all custom object names (except the `customer` object) with your `app_id`. |
`display_name` | The user-friendly name used for display within the UI (should be plural). You must prefix all custom object names (except the `customer` object) with your app name. |
`alias` | (Optional) The singular name of the object. |
`fields.name` | The name of the field used for API/SDK calls, CSV uploads, and liquid. Must be unique within the object. |
`fields.display_name` | The user-friendly name used for display within the UI. Must be unique within the object. |
`fields.type` | Must be `string`, `number`, `boolean`, or `timestamp`. |
`fields.primary` | (Optional) Boolean. Defaults to `false`. `true` – The field listed is the primary key for the containing object.\ `false` – The field listed is not the primary key for the containing object. At least one primary key is required for new objects. |
`relations` | (Optional) Should be defined on the parent object. |
`relations.name` | The name of the relationship used for API/SDK calls and liquid. |
`relations.display_name` | The user-friendly name used for display within the UI. |
`relations.child_object` | The child object that is connected to this object. |
`relations.join_fields.parent` | Any field on this object that you want to relate to another object. |
`relations.join_fields.child` | Must be a primary key on the child object. |
Create static schema
With static schema, when users install your app, Connect Platform for ODP parses all files within src/schema and creates all described objects and fields. You can either edit the schema of the customer object or create new custom objects:
- To add a field or an identifier to the customer object, create a file named customers.yaml within the src/schema folder.
- To add a custom object, create a file named <plural_object_name>.yaml within the src/schema folder. For example, a file named acme_tickets.yaml for the acme_tickets object.
Note The file names within the src/schema folder must match the name of an existing object or the name of the custom object you want to create.
Below is an example of an src/schema/acme_tickets.yaml file:
name: acme_tickets
display_name: Acme Tickets
alias: acme_ticket
fields:
- name: acme_ticket_id
display_name: Acme Ticket ID
type: string
primary: true
- name: tag_id
display_name: Tag ID
type: string
relations:
- name: acme_ticket_tag
display_name: Acme Ticket Tag
child_object: acme_ticket_tags
join_fields:
- parent: tag_id
child: acme_ticket_tag_idCreate identifiers
Additionally, for the customers object, you can create custom identifiers. For example:
name: customers
identifiers:
- name: acme_ios_push_token
display_name: Acme iOS Push Token
merge_confidence: high
messaging: trueProperty | Description |
|---|---|
`identifiers.name` | The singular name of the identifier used within API and SDK calls. Must be unique within the object and prefixed by your `app_id`. All identifiers must include one of the following suffixes: `id`, `hash`, `number`, `token`, `alias`, `address`, `key` |
`identifiers.display_name` | The user-friendly name used in the ODP UI to refer to the identifier. Must be unique within the object. |
`identifiers.merge_confidence` | The confidence level for the identifier. Must be `high` or `low`. For more information on identifier confidence levels, see [Identifier confidence](https://support.optimizely.com/hc/en-us/articles/4407767067149-Overview-of-customer-identity-and-resolution#h_01HH0HXXJT5C49WKMHQQ5YFWSB). |
`identifiers.messaging` | (Optional) Boolean. Defaults to `false`. `true` – You can use this identifier to contact the customer on a channel.\ `false` – You can not use this identifier to contact the customer on a channel. |
When you create an identifier, ODP creates three fields:
- The plural version of the identifier (for example, ios_push_tokens) on the Customer object that contains a list of 25 last seen identifiers for that customer.
- The singular version of the identifier (for example, ios_push_token) on the Customer object that contains the last seen identifier for that customer.
- An event audit version that is populated when an event comes in with the singular version (for example, event_ios_push_token).
All events and data should use the singular version of the identifier name (for example, ios_push_token).
Create dynamic schema
Use dynamic schema to create customer fields per client. You cannot create these objects and fields in the schema YAML files because they differ for each install. Connect Platform for ODP provides a number of methods to create fields programmatically. For more information, see the Node SDK reference for Fields, Objects, and Relationships.
Usually, dynamically creating objects and fields is performed in lifecycle callback functions. For example, onInstall or onUpdate.
Note When updating schema dynamically, you should always check if the object or field already exists.
Below is an example of dynamically creating an acme_tickets Object.
import {z} from '@zaiusinc/node-sdk';
await z.schema.createObject({
'name': 'acme_tickets',
'display_name': 'Acme Tickets',
'alias': 'acme_ticket',
'fields': [
{
'name': 'acme_ticket_id',
'display_name': 'Acme Ticket ID',
'type': 'string',
'primary': true
},
{
'name': 'tag_id',
'display_name': 'Tag ID',
'type': 'string'
}
],
'relations': [
{
'name': 'acme_ticket_tag',
'display_name': 'Acme Ticket Tag',
'child_object': 'acme_ticket_tags',
'join_fields': [{
'parent': 'tag_id',
'child': 'acme_ticket_tag_id'
}]
}
]
});Below is an example of dynamically creating a tag_id Field.
import {z} from '@zaiusinc/node-sdk';
await z.schema.createField('acme_tickets', {
'name': 'tag_id',
'display_name': 'Tag ID',
'type': 'string'
});Below is an example of dynamically creating an acme_ticket_tag Relationship.
import {z} from '@zaiusinc/node-sdk';
await z.schema.createRelation('acme_tickets', {
'name': 'acme_ticket_tag',
'display_name': 'Acme Ticket Tag',
'child_object': 'acme_ticket_tags',
'join_fields': [{
'parent': 'tag_id',
'child': 'acme_ticket_tag_id'
}]
});