Import & Export the Schema

The Import & Export feature in Iteratively allows customers to more tightly integrate Iteratively's core capabilities — analytics schema management, type-safe analytics library generation, and analytics QA — with their existing engineering workflows.

It enables developers to interact with Iteratively directly from the command line to read and write their team's core analytics metadata: events, global properties, and context.

Itly CLI

The Itly CLI exposes import and export operations via two new commands: import and export.

itly import [{source}] [-f {path-to-file}] [-t {token}]
  • Imports a tracking plan stored in a JSON file into the user's account
  • If {source} is present, the import only applies to this source
  • If {source} is absent, the import is account-wide
  • -f {path-to-file} contains the JSON as specified later in this document
  • -t {token} will bypass .itlyrc-based login and use the provided token for authentication
itly export [{source}] [-f {path-to-file}] [-t {token}]
  • Exports a tracking plan from the user's account into a JSON file
  • If {source} is present, only the source's events are exported
  • If {source} is absent, the complete schema is exported
  • -f {path-to-file} will contain the JSON as specified later in this document
  • -t {token} will bypass .itlyrc-based login and use the provided token for authentication

Authentication

The token used for -t/--token is a user's personal API authentication token. The token grants the bearer the same level of authorization as the user the token belongs to.

Authentication tokens are generated and managed in the web application under Settings. The tokens do not expire and can be instantly disabled.

JSON Format

When serialized to a text file, a company's tracking plan is stored in a machine- and human-readable format.

If a user imports or exports without providing a {source}, import or export is account-wide:

  • events: an array of all events in the company's tracking plan
    • sources: an array of sources the event should be linked to
    • schema: the JSON Schema representation of the event and its properties
  • identify and group: an object representing user and group traits
    • schema: the JSON Schema representation of user and group traits
  • context: an array of all contexts created in a company's tracking plan; each context belongs to one specified source
    • schema: the JSON Schema representation of the context

If a user imports or exports with a {source}, only the schema relevant to that source is imported or exported:

  • events: an array of all events in the company's tracking plan
    • schema: the JSON Schema representation of the event and its properties

For example:

{
events: [
{
sources: [{ name: "web" }, { name: "cli" }],
schema: {
"$id": "https://iterative.ly/company/0adfd673-c53b-462c-bf88-84c7605286a4/event/35e19a7e-14f5-4638-9058-b77b8028aa04",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "User Signed In",
"description": "Called when a user signs in.",
"type": "object",
"properties": {
"platform": {
"description": "The platform the user is signing in on.",
"type": "string"
}
},
"additionalProperties": false,
"required": [
"platform"
]
}
}
],
identify: {
schema: {
"$id": "https://iterative.ly/company/0adfd673-c53b-462c-bf88-84c7605286a4/identify",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Identify Properties",
"type": "object",
"properties": {
"firstName": {
"description": "The user's first name.",
"type": "string"
}
},
"additionalProperties": false,
"required": [
"firstName"
]
}
},
context: {
schema: {
"$id": "https://iterative.ly/company/0adfd673-c53b-462c-bf88-84c7605286a4/context-web",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Context Properties",
"type": "object",
"properties": {
"version": {
"description": "The version of the application.",
"type": "string"
}
},
"additionalProperties": false,
"required": [
"version"
]
}
}
}

JSON Schema:

{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"events": {
"type": "array",
"items": {
"type": "object",
"properties": {
"sources": {
"type": "array",
"items": {
"type": "string"
}
},
"schema": {
"type": "object"
}
},
"additionalProperties": false
}
},
"identify": {
"type": "object",
"properties": {
"schema": {
"type": "object"
}
},
"additionalProperties": false
},
"group": {
"type": "object",
"properties": {
"schema": {
"type": "object"
}
},
"additionalProperties": false
},
"context": {
"type": "array",
"items": {
"type": "object",
"properties": {
"source": {
"type": "string"
},
"schema": {
"type": "object"
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}

Account-Wide Import Without Source

The import command reads a new tracking plan and updates the account to match the new spec.

itly import -f {path-to-file} -t {token}

To determine the changes that need to be made, the import feature adheres to the following rules.

For events:

  • If an $id is present, it is used to map the incoming event to an existing event. Only IDs generated by Iteratively are accepted.
  • If an $id is absent, the JSON schema's title is used instead.
  • If an incoming event matches no existing event, it is created and linked to the sources specified in sources.
  • If an incoming event matches an existing event, the existing event is updated to match the specified list of sources and the event's new schema.
    • The incoming event properties update the existing's events properties according to the same rules. A property's name is used exclusively to match an incoming property to an existing property.
  • If an event exists in the user's account but no incoming event matches it, the existing event is deleted.

This logic is identical to global properties (identify and group) and contexts.

During import, any changes made to the tracking plan's events, properties, contexts, etc. are audited and will appear in the event's as well as the company's recent activity feed.

Source-Specific Import With Source

The import command reads the new source specific tracking plan and updates the account to match the new spec.

itly import {source} -f {path-to-file} -t {token}

The behavior of a source-specific import is identical to the behavior of an account-wide import, with a few key exceptions:

  • A source-specific import imports all events in the passed in schema and associates them with the provided source
  • Because a single event can be associated with multiple sources, if the same event appears in multiple schema files, the maintainers of the schema files must take care to ensure the same event's definition stays consistent
  • If an event disappears from a schema file for a particular source, that event is deleted if it is not also associated with another source; it ramains in place otherwise and the provided source is simply removed
  • If an event appears in a schema file for a particular source, that event is created if it doesn't already exist; it is simply updated otherwise and the particular source is added to it
  • The sources field in the serialized schema is ignored