Skip to content
Documentation

Self-hosted personalization: requirements

If you are hosting your own Unomi instance rather than using Dropsolid's managed setup, there are a few things you need to configure before personalization will work correctly.

Geolocation

To use geolocation-based personalization, you need the MaxMind GeoLite2-City database installed on your Unomi server.

You also need to enable the geolocation feature for your CDP in Platform. Only then will the visitor's IP address be sent to Unomi for lookup. The visitor’s IP address does not get saved anymore, it is only used to determine the location. The location does get saved in the visitor’s profile.

Once enabled, tell Unomi where to find the database file. You can do this in one of two ways:

  • In your unomi.custom.system.properties file, set the org.apache.unomi.ip.database.location property:
    org.apache.unomi.ip.database.location=/usr/share/GeoIP/GeoLite2-City.mmdb
  • Or via the environment variable UNOMI_IP_DB:
    UNOMI_IP_DB=/opt/apache-unomi/database/GeoLite2-City.mmdb

Info

Unomi reads the visitor's IP address from the X-Forwarded-For header. Make sure this header is not being stripped or blocked anywhere in your infrastructure, or geolocation will not work.

Scope

If you are running Unomi version 2 or higher, you need to create a scope for your CDP. A scope ties events and profiles to a specific Unomi context, which is how Dropsolid Personalization identifies data belonging to your instance. Events without an existing scope will be rejected by Unomi.

Use your CDP UUID as the scope ID. Create it with the /cxs/scopes endpoint:

curl --request POST \
  --url <unomi_url>/cxs/scopes \
  --header '<authorization_header>' \
  --header 'content-type: application/json' \
  --data '{
  "itemId": "<cdp_uuid>",
  "metadata": {
    "id": "<cdp_uuid>",
    "name": "<scope_name>"
  }
}'

You can find your CDP UUID in the capture script url in the Developer → Capture tab of your CDP in Platform. The url of the capture script is built like: https://datacapture.dropsolid.com/<cdp_uuid>/capture.js.

JSON schemas

If you are running Unomi version 2 or higher, you need JSON schemas for our custom events. Unomi uses these schemas to validate incoming events, so any event type that does not have a matching schema will be rejected.

JSON schemas are not included in Dropsolid's Unomi patches, so you have full control over them: you can use the schemas we provide below, adapt them, or write your own. Unlike schemas baked into Unomi, schemas created via the API can be updated at any time.

Create a JSON schema

Use the /cxs/jsonSchema endpoint to create a schema:

curl --request POST \
  --url <unomi_url>/cxs/jsonSchema \
  --header '<authorization_header>' \
  --header 'content-type: application/json' \
  --data '{
  "$id": "https://unomi.apache.org/schemas/json/events/dataCaptured/1-0-0",
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "self": {
    "vendor": "org.apache.unomi",
    "target": "events",
    "name": "dataCaptured",
    "format": "jsonschema",
    "version": "1-0-0"
  },
  "title": "DataCapturedEvent",
  "type": "object",
  "allOf": [
    {
      "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0"
    }
  ],
  "properties": {
    "eventType": {
      "type": "string",
      "pattern": "^dataCaptured$"
    },
    "scope": {
      "type": ["string"],
      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
    },
    "source": {
      "type": "object",
      "properties": {
        "itemType": { "type": "string" },
        "scope": { "type": "string" },
        "itemId": { "type": "string" }
      }
    },
    "properties": {
      "type": "object",
      "maxProperties": 500
    }
  },
  "unevaluatedProperties": false
}'

You can use a different $id if you prefer. Just make a note of it, as you will need it to update or delete the schema later. The version number in the $id is optional.

Warning

Avoid duplicate schemas for the same event type. If multiple schemas exist for the same event, Unomi will use whichever appears first when you call the list endpoint. That order is determined by hashed IDs, which is not easy to predict. To avoid this, either update your existing schema instead of creating a new one, or delete the old schema before creating a replacement.

Get all JSON schemas

Retrieve all schemas currently registered in Unomi, with the /cxs/jsonSchema endpoint:

curl --request GET \
  --url <unomi_url>/cxs/jsonSchema \
  --header '<authorization_header>'

Get a JSON schema

Retrieve a specific schema by its ID, with the /cxs/jsonSchema/query endpoint:

curl --request POST \
  --url <unomi_url>/cxs/jsonSchema/query \
  --header '<authorization_header>' \
  --header 'content-type: text/plain' \
  --data https://unomi.apache.org/schemas/json/events/dataCaptured/1-0-0

Delete a JSON schema

Delete a schema by its ID, with the /cxs/jsonSchema/delete endpoint:

curl --request POST \
  --url <unomi_url>/cxs/jsonSchema/delete \
  --header '<authorization_header>' \
  --header 'content-type: text/plain' \
  --data https://unomi.apache.org/schemas/json/events/dataCaptured/1-0-1

Validate an event

You can use the /cxs/jsonSchema/validateEvent endpoint to test whether an event passes schema validation:

curl --request POST \
  --url <unomi_url>/cxs/jsonSchema/validateEvent \
  --header '<authorization_header>' \
  --header 'content-type: application/json' \
  --data '{
  "eventType": "dataCaptured",
  "scope": "<cdp_uuid>",
  "source": {
    "itemType": "page",
    "scope": "<cdp_uuid>",
    "itemId": "home"
  },
  "properties": {
    "te__domain": "example.com",
    "te__uuid": "<event_uuid>"
  }
}'

Our JSON schemas

These are the schemas Dropsolid provides for the event types that are supported by default in Dropsolid’s custom Unomi patches & plugins. You can register these as-is or use them as a starting point for your own.

So these are the JSON schemas you have to add (or a derivative of them), otherwise the data capturing events will be rejected by Unomi.

dataCaptured

{
  "$id": "https://unomi.apache.org/schemas/json/events/dataCaptured/1-0-0",
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "self": {
    "vendor": "org.apache.unomi",
    "target": "events",
    "name": "dataCaptured",
    "format": "jsonschema",
    "version": "1-0-0"
  },
  "title": "DataCapturedEvent",
  "type": "object",
  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }],
  "properties": {
    "eventType": { "type": "string", "pattern": "^dataCaptured$" },
    "scope": {
      "type": ["string"],
      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
    },
    "source": {
      "type": "object",
      "properties": {
        "itemType": { "type": "string" },
        "scope": { "type": "string" },
        "itemId": { "type": "string" }
      }
    },
    "properties": { "type": "object", "maxProperties": 500 }
  },
  "unevaluatedProperties": false
}

dataClassified

{
  "$id": "https://unomi.apache.org/schemas/json/events/dataClassified/1-0-0",
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "self": {
    "vendor": "org.apache.unomi",
    "target": "events",
    "name": "dataClassified",
    "format": "jsonschema",
    "version": "1-0-0"
  },
  "title": "DataClassifiedEvent",
  "type": "object",
  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }],
  "properties": {
    "eventType": { "type": "string", "pattern": "^dataClassified$" },
    "scope": {
      "type": "string",
      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
    },
    "source": {
      "type": "object",
      "properties": {
        "itemType": { "type": "string" },
        "scope": {
          "type": "string",
          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
        },
        "itemId": { "type": "string" }
      }
    },
    "properties": {
      "type": "object",
      "properties": {
        "classification_properties": {
          "type": "object",
          "properties": {
            "te__uuid": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            },
            "do__probability": { "type": "array" }
          }
        },
        "te__uuid": {
          "type": "string",
          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
        }
      }
    }
  },
  "unevaluatedProperties": false
}

customData

{
  "$id": "https://unomi.apache.org/schemas/json/events/customData/1-0-0",
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "self": {
    "vendor": "org.apache.unomi",
    "target": "events",
    "name": "customData",
    "format": "jsonschema",
    "version": "1-0-0"
  },
  "title": "CustomDataEvent",
  "type": "object",
  "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }],
  "properties": {
    "eventType": { "type": "string", "pattern": "^customData$" },
    "scope": {
      "type": "string",
      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
    },
    "source": {
      "type": "object",
      "properties": {
        "itemType": { "type": "string" },
        "scope": {
          "type": "string",
          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
        },
        "itemId": { "type": "string" }
      }
    },
    "properties": { "type": "object", "maxProperties": 15 }
  },
  "unevaluatedProperties": false
}