Developer
User guidesDeveloper websiteHelp centerLog in
  • Welcome!
  • Organisations structure
    • Datamart
    • Users and roles
  • User points
    • User identifiers
      • Networks IDs
        • Device-based Network IDs
          • Custom Device ID integration
          • ID5
          • First ID
        • User-based Network IDs
          • Custom User ID integration
          • UTIQ martechpass
      • Accounts
      • Emails
      • Device identifiers
    • User activities and events
    • Compartments
    • User profiles
    • User segments
    • Hyper point & Quarantine
  • Data model
    • Defining your schema
    • Computed fields
      • Concepts
      • Setup
      • Development
      • Examples
  • Data ingestion
    • Real time user tracking
      • Website tracking
      • Mobile apps tracking
      • Ads exposure tracking
      • AMP tracking
      • Conversions tracking
      • Email views and clicks
      • Tracking API
      • Event rules
      • Activity analyzers
    • Bulk processing
      • Imports
        • User activities import
        • User profiles import
        • User choices import
        • Segments import
      • Deletions
        • User identifiers deletion
        • Device points deletion
        • User points deletion
      • User identifiers association
      • Integration batch
    • Activities analytics
    • Data warehouse
      • Preliminary setup
        • BigQuery
      • Create data warehouse
  • Querying your data
    • OTQL queries
    • OTQL examples
    • GraphQL queries
    • UserPoint API
    • User activities
    • Activities analytics queries
      • API Quickstart
      • Dimensions and metrics
      • Use cases
    • Funnel API
  • Alerting
    • Alert configurations
  • Data visualisation
    • Quickstart
    • Dashboards
    • Sections and cards
    • Charts
    • Datasets and data sources
      • Using a data file data source
    • Transformations
    • Filters
    • Cookbook
    • Reference
  • Advanced usages
    • Audience segmentation
      • Audience features
      • Segment builders
      • Audience segment metrics
      • Audience segment feed
        • Building new feeds
        • Monitoring a feed
        • Curated Audiences (SDA)
      • Edge segments
      • Cohort-based Lookalike
    • Contextual targeting
      • Setup
      • Activation
        • Google Ad Manager
        • Xandr (through prebid.js)
      • API documentation
    • Exporting your data
      • Query Exports
      • Datamart replication
    • Data privacy compliance
      • User choices
      • Cleaning rules
      • Exercise of user rights
      • Cookies
    • Campaigns
    • Automations
      • Email routers
      • Email renderers
      • Opt-in provider
      • Custom action plugins
      • Usage limits for automations
    • Plugins
      • Concepts
      • Creation & Deployment
      • Coding your plugin
      • Manage existing plugins
      • Layouts
      • Presets
      • Monitoring
      • Throttling
      • Batching (for external feeds)
    • Platform monitoring
      • Resources usage
        • Dimensions and metrics
      • Collection volumes
        • Dimensions and metrics
      • Events ingestion monitoring
        • Dimensions and metrics
    • Data Clean Room
      • Bunker
      • Clean room
  • Resources
    • Tutorial: Data Ingestion
      • Your first events
        • Add the mediarithmics tag
          • Getting the tag
          • Adding the tag
        • Send events using the tag
          • Adding event properties
          • Finding the UserEvent type in your schema
          • Matching your schema
          • Standard events
      • Your first bulk imports
        • API basics
          • Authentication
          • Your first API call
        • Send documents using the API
          • Requirements
          • Sending documents
    • Using our API
      • Authentication
    • Tools & libraries
      • mics CLI
      • JS Tag
      • Plugin SDK
    • Data cubes
      • Creating a report
      • Reference
Powered by GitBook
On this page
  • How-to
  • User profile import command
  • Example
  • Possible update strategies when updating existing user profiles
  • PARTIAL_UPDATE and PARTIAL_DELETE
  • FORCE_REPLACE
  • Legacy parameters

Was this helpful?

Export as PDF
  1. Data ingestion
  2. Bulk processing
  3. Imports

User profiles import

PreviousUser activities importNextUser choices import

Last updated 3 days ago

Was this helpful?

Use this feature to UPSERT or DELETE in your datamart.

How-to

Use the endpoints to create a with theUSER_PROFILEdocument type and APPLICATION_X_NDJSON mime type. Only ndjson data is supported for user profiles.

You can, of course, upload multiple user profiles at once. Note the uploaded data is in ndjson and not json. That means the different profiles are not separated by commas, but by a line separator \n

Then, create anwith your user profile import commands formatted in ndjson .

User profile import command

Each line in the uploaded file can have the following properties:

field
type
description

operation

Enum

Either UPSERT or DELETE

compartment_id

String (Optional)

user_account_id

String (Optional)

email_hash

String (Optional)

user_agent_id

String (Optional)

update_strategy

Enum (Optional)

Only considered when operation == UPSERT Values are PARTIAL_UPDATE, PARTIAL_DELETE, FORCE_REPLACE

user_profile

JSON Object (Optional)

Mandatory when operation == UPSERT.

When importing profiles with identifiers, only one identifier is allowed per line. For example, you shouldn't specify the user agent ID if the Email Hash is already used in a line.

Example

First create the document import using the call below. You can also reuse a document import that was previously created

curl -X POST \
  https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports \
  -H 'Authorization: <YOUR_API_TOKEN>' \
  -H 'Content-Type: application/json' \
  -d '{
	"document_type": "USER_PROFILE",
	"mime_type": "APPLICATION_X_NDJSON",
	"encoding": "utf-8",
	"name": "<YOUR_DOCUMENT_IMPORT_NAME>"
}'

Each user profile import you do will be a new execution of the document import created. Here is an example :

# Here we use the combination of compartment_id and user_account_id acting as identifier
curl -X POST \
  https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
  -H 'Authorization: <API_TOKEN>' \
  -H 'Content-Type: application/x-ndjson' \
  -d '{ 
        "operation": "UPSERT",
        "compartment_id": "<COMPARTMENT_ID>", 
        "user_account_id": "<USER_ACCOUNT_ID>",
        "user_profile": {
              this": "is",
              "a":"test"
        }
      }'

Possible update strategies when updating existing user profiles

When doing an UPSERT if you want to update existing profiles in your datamart you should use the update_strategy field.

PARTIAL_UPDATE and PARTIAL_DELETE

If you wish to perform targeted updates on existing profiles without overwriting the whole existing user profile object, you should use the PARTIAL_UPDATE or PARTIAL_DELETE values of the update_strategy field.

You should mark a field with the directive @UpdateStrategyKey inside of each object you would like to make updates on. Inside of a given object, the field that has the directive will serve to identify the given object based on the value of this field in the update request.

This will allow you to alter data of inner objects or arrays of the user profile and in particular : add objects or update fields inside of objects or arrays. This is especially useful for intricated structures such as arrays of objects inside of objects, arrays of arrays of objects...

  • It is possible to define a hierarchy of inner objects while using @UpdateStrategyKey at each level

  • However, @UpdateStrategyKey should only be set to one property inside a given object

#This is allowed
type LoyaltyCard {
  card_id:String @UpdateStrategyKey
  benefits: Int
  last_visit_date: String
  other_information : [OtherInformation]
}
type OtherInformation {
	info_id: String @UpdateStrategyKey
}

################################

#This is not allowed
type LoyaltyCard {
  card_id:String @UpdateStrategyKey
  benefits: Int @UpdateStrategyKey
  last_visit_date: Date  
}

Example

Let's consider this simplified schema on which you would like to update values of the LoyaltyCard object without overwriting the whole profile.

## Schema extract

type UserProfile {
   loyalty:Loyalty
}

type Loyalty {
  cards:[LoyaltyCard] #it's an array of objects

}

type LoyaltyCard {
  card_id:String @UpdateStrategyKey # we add the directive to be able to update LoyaltyCard by referecing card_id in the update request
  benefits: Int
  last_visit_date: String
}

Given a stored profile like this one :

// Existing profile:
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "card_id": "abc",
        "benefits": 200,
        "last_visit_date": "2024-01-01"
      }
    ]
  }
}

And this import execution using the PARTIAL_UPDATE for instance

# Partial update of the benefits of a given card 
curl -X POST \
  https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
  -H 'Authorization: <API_TOKEN>' \
  -H 'Content-Type: application/x-ndjson' \
  -d '{ 
        "operation": "UPSERT",
        "compartment_id": "<COMPARTMENT_ID>", 
        "user_account_id": "<USER_ACCOUNT_ID>",
        "update_strategy": "PARTIAL_UPDATE",
        "user_profile": {
          "compartment_id": "<COMPARTMENT_ID>",
          "user_account_id": "<USER_ACCOUNT_ID>",
          "loyalty": {
            "cards": [
              {
                "card_id": "abc", #value of the field marked with @UpdateStrategyKey of the object to update
                "benefits": 500 #we want to update the benefits value of the card with "card_id":"abc"
              }
            ]
          }
        }
      }'

The new profile is updated with the new value :

// New profile is
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "card_id": "abc",
        "benefits": 500,
        "last_visit_date": "2024-01-01"
      }
    ]
  }
}

Application use cases of PARTIAL_UPDATE and PARTIAL_DELETE

#1 - Add an inner object - PARTIAL_UPDATE

// Existing profile
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "card_id": "abc",
        "benefits": 500,
        "last_visit_date": "2024-01-01"
      }
    ]
  }
}

//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [ //adding a new cards object
      {
        "card_id": "def",
        "benefits": 100,
        "last_visit_date": "2025-01-01"
      }
    ]
  }
}

//New profile

{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [ // the cards object contains both cards
      {
        "card_id": "abc",
        "benefits": 500,
        "last_visit_date": "2024-01-01"
      },
      {
        "card_id": "def",
        "benefits": 100,
        "last_visit_date": "2025-01-01"
      }
    ]
  }
}

#2 - Update an inner object property - PARTIAL_UPDATE

// Existing profile
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "card_id": "abc",
        "benefits": 500,
        "last_visit_date": "2024-01-01"
      }
    ]
  }
}

//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [ //request changing the benefits value of the existing card
      {
        "card_id": "abc", // value of the field marked with @UpdateStrategyKey of the inner object to update
        "benefits": 100
      }
    ]
  }
}

//New profile

{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [ // 
      {
        "card_id": "abc",
        "benefits": 100, // value has been updated
        "last_visit_date": "2024-01-01"
      }
    ]
  }
}

Remark : arrays of scalar values are treated as scalars. See example below :

// Extract of existing profile
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "my_array_of_scalars": [1,2,3],
  ...
}

//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "my_array_of_scalars": [4,5,6],
  ...
}

//New profile
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "my_array_of_scalars": [4,5,6], // the value of the property has been replaced by the new value
  ...
}

#3 - Delete an inner object property - PARTIAL_UPDATE

For a non mandatory value you can also set a given field to null (but not an object directly). For instance in the previous example you could have done the following :

// Existing profile
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "card_id": "abc",
        "benefits": 500,
        "last_visit_date": "2024-01-01"
      }
    ]
  }
}

//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [ 
      {
        "card_id": "abc",
        "benefits": null // set the value to null
      }
    ]
  }
}

//New profile

{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [ // benefits value has been cleared
      {
        "card_id": "abc",
        "last_visit_date": "2024-01-01"
      }
    ]
  }
}

#4 - Update inner object and add new object - PARTIAL_UPDATE

// Existing profile
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "card_id": "abc",
        "benefits": 500,
        "last_visit_date": "2024-01-01"
      }
    ]
  }
}

//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [ 
      {
        "card_id": "abc",
        "benefits": 100 //updating exsisting object
      },
      {
        "card_id": "def", //adding a new object
        "benefits": 600,
        "last_visit_date": "2025-01-01"
      }
    ]
  }
}

//New profile

{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "card_id": "abc",
        "benefits": 100, // value has been updated
        "last_visit_date": "2024-01-01"
      },
      {
        "card_id": "def", // object has been added
        "benefits": 600,
        "last_visit_date": "2025-01-01"
      }
    ]
  }
}

#5 - Delete an inner object - PARTIAL_DELETE

//Existing profile

{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "card_id": "abc",
        "benefits": 100,
        "last_visit_date": "2024-01-01"
      },
      {
        "card_id": "def",
        "benefits": 600,
        "last_visit_date": "2025-01-01"
      }
    ]
  }
}

//Profile in update payload with update_strategy == PARTIAL_DELETE
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [ 
      {
        "card_id": "abc" // value of the field marked with @UpdateStrategyKey of the inner object to delete
      }
    ]
  }
}

//New profile

{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [ // the card with card_id = "abc" has been deleted
      {
        "card_id": "def",
        "benefits": 600,
        "last_visit_date": "2025-01-01"
      }
    ]
  }
}

If you wish to delete a specific property value inside an object, you should use PARTIAL_UPDATE. Please refer to use case #3.

Constraints and limitations

Schema related constraints :

The update request must respect the datamart schema :

  • If a property is in the payload of the request but not declared in the schema, the whole request will fail. However, if a property is already present in the profile but not declared in the schema, it will not be overwritten by a partial update or delete. In fact it will not be possible to update such property unless using FORCE_REPLACE

  • If the types of the properties in the payload of the request do not respect the schema, the whole request will fail.

Limitations :

  • If a property in the schema has a directive such as @Property(path: “[parent].property”) (referencing [parent] in path) : this property cannot be updated with the partial update

  • Updatable properties cannot be computed values such as : computed field, ML function, results of function.

FORCE_REPLACE

When importing user profiles using UPSERT, if you wish to update existing profiles by completely overwriting the existing profiles you should use the FORCE_REPLACE value of the update_strategy field : the user profile will be completely replaced by the object passed in the user_profile field.

# Stored profile:
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "benefits": 200,
        "card_id": "abc",
        "last_visit_date": "2024-01-01"
      }
    ]
  }
}


# New profile in request payload
curl -X POST \
  https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
  -H 'Authorization: <API_TOKEN>' \
  -H 'Content-Type: application/x-ndjson' \
  -d '{ 
        "operation": "UPSERT",
        "compartment_id": "<COMPARTMENT_ID>", 
        "user_account_id": "<USER_ACCOUNT_ID>",
        "update_strategy": "FORCE_REPLACE",
        "user_profile": {
          "compartment_id": "<COMPARTMENT_ID>",
          "user_account_id": "<USER_ACCOUNT_ID>",
          "loyalty": {
            "cards": [
              {
                "benefits": 500,
                "card_id": "xyz",
                "last_visit_date": "2025-01-01"
              }
            ]
          }
        }
      }'

# New saved profile:
{
  "compartment_id": "<COMPARTMENT_ID>",
  "user_account_id": "<USER_ACCOUNT_ID>",
  "loyalty": {
    "cards": [
      {
        "benefits": 500,
        "card_id": "xyz",
        "last_visit_date": "2025-01-01"
      }
    ]
  }
}

Legacy parameters

field
type
description

force_replace

Boolean (Optional)

Mandatory when the operation is UPSERT. If true, then the User Profile will be completely replaced by the object passed in the user_profile field. If false, the object passed in the user_profile field will be merged with the existing User Profile of the User Point.

merge_objects

Boolean (Optional)

Only considered if force_replace is false.

Manage the comportement between two objects with a same property.

If false (default value), the new object overrides the existing one.

More details on merge_objects behavior :

# Stored profile:
{
  "my_property_1": "value1",
  "my_property_2": "value1",
  "my_array_property": ["value1"]
  "my_array_object_property": [
    {
      "my_sub_array_object_property_1": "value1",
      "my_sub_array_object_property_2": "value1"
    }
  ],
  "my_object_property": {
    "my_sub_object_property_1": "value1",
    "my_sub_object_property_2": "value1"
  }    
}


# New profile in request payload
curl -X POST \
  https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
  -H 'Authorization: <API_TOKEN>' \
  -H 'Content-Type: application/x-ndjson' \
  -d '{ 
        "operation": "UPSERT",
        "compartment_id": "<COMPARTMENT_ID>", 
        "user_account_id": "<USER_ACCOUNT_ID>",
        "force_replace": false,
        "merge_objects": true,
        "user_profile": {
          "my_property_2": "value2",
          "my_property_3": "value3",
          "my_array_property": ["value2"]
          "my_array_object_property": [
            {
              "my_sub_array_object_property_2": "value2"
              "my_sub_array_object_property_3": "value3"
            }
          ],
          "my_object_property": {
            "my_sub_object_property_2": "value2"
            "my_sub_object_property_3": "value3"
          }    
        }
      }'

# New saved profile:
{
  "my_property_1": "value1",
  "my_property_2": "value2", # override scalar property
  "my_property_3": "value3",
  "my_array_property": ["value1","value2"] # merge arrays
  "my_array_object_property": [ # merge arrays
    {
      "my_sub_array_object_property_1": "value1"
      "my_sub_array_object_property_2": "value1"
    },
    {
      "my_sub_array_object_property_2": "value2"
      "my_sub_array_object_property_3": "value3"
    }
  ],
  "my_object_property": { # merge objects
    "my_sub_object_property_1": "value1"
    "my_sub_object_property_2": "value2" # override scalar property within object
    "my_sub_object_property_3": "value3"
  }    
}

The Compartment ID, acting as a user in correlation with user_account_id

The User Account ID, acting as an in correlation with compartment_id

The Email Hash, acting as an

The User Agent ID, acting as an

JSON Object representing the User Profile. Please refer to the for more information.

These options work together with a @UpdateStrategyKey that should be defined on the schema of the datamart you are working on. You should first in order to include this new directive.

If true the new object is merged in deep to the existing one (see ).

user profile object
example
user profiles
bulk import
update the schema
identifier
identifier
identifier
identifier
directive
document import
execution