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.propertiesfile, set theorg.apache.unomi.ip.database.locationproperty:
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
}