Chameleon
Chameleon is a product adoption platform for building in-product Experiences — Tours, Microsurveys, Launchers, and Tooltips. Datafly Signal forwards your first-party events to Chameleon’s Observe API server-side, so you can target Experiences in real time on what users actually do, without adding another client-side script.
Because Signal delivers from your own server, Chameleon receives events even when the browser is offline, an ad blocker is active, or the user has navigated away.
Prerequisites
- A Chameleon account with the Observe (events) feature enabled.
- A Chameleon Secret API key. Generate one in Chameleon under Settings → Tokens (
app.chameleon.io/settings/tokens). Use the Secret API key, not the public account token — the account token is rejected with a401once identity verification is enabled. Tokens can only be downloaded once, so store it securely. - The same user identifier (
uid) you pass to Chameleon’s in-app snippet (chmln.identify(uid, ...)). Events must carry the sameuidso Chameleon attaches them to the right profile.
Configuration
| Field | Required | Description |
|---|---|---|
| Account Secret (Secret API Key) | Yes | Your Chameleon Secret API key, sent as the X-Account-Secret header. |
Configure in Signal
- In the Signal dashboard, open Integrations and add Chameleon.
- Paste your Account Secret (Secret API Key).
- Attach the Chameleon blueprint to a pipeline. The default Product / SaaS preset maps
page,Signed Up,Logged In,Feature Used,Trial Started, andOrder Completed. - Save and enable the pipeline.
API Endpoint
Signal delivers each event with a POST to Chameleon’s Observe events hook:
POST https://api.chameleon.io/v3/observe/hooks/events
X-Account-Secret: <your Secret API key>
Content-Type: application/jsonA successful response returns the created event id:
{ "event": { "id": "5f3c4232c712de665632a2a3" } }Identity Signals
Chameleon attaches each event to a user profile using the identity fields in the payload. At least one of these must be present:
| Signal field | Chameleon field | Notes |
|---|---|---|
user_id | uid | Your backend user id. Should match the uid passed to chmln.identify(). Required by the default preset. |
email (trait) | email | Used to resolve a profile when no uid is available. |
Chameleon stores raw first-party identifiers, so Signal does not hash uid or email for this integration. There is no advertising consent field on the Observe API — this is first-party product-adoption data — so no consent mapping is applied.
Event Mapping
The event name is sent in the required name field. All other mapped properties are delivered as flat custom event properties; Chameleon normalises property names to lower_snake_case on ingest and stores up to 768 bytes per scalar value.
| Signal event | Chameleon name |
|---|---|
page | Page Viewed |
Signed Up | Signed Up |
Logged In | Logged In |
Feature Used | Feature Used |
Trial Started | Trial Started |
Order Completed | Order Completed |
Example
A Feature Used event sent from Datafly.js:
datafly.track("Feature Used", {
feature_name: "csv_export",
feature_area: "reports"
});Resulting payload delivered to Chameleon:
{
"uid": "user_8821",
"email": "leon@example.com",
"name": "Feature Used",
"feature_name": "csv_export",
"feature_area": "reports"
}Testing
- Trigger an event on your site (for example, sign up or use a tracked feature) with a known
uid. - In Chameleon, open the matching User Profile and confirm the event appears in the activity timeline within a few seconds.
- Build an Experience targeted on that event and confirm it triggers for the user.
- In Signal’s Event Debugger, confirm the outbound request returned a
200with anevent.idin the response.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
401 Unauthorized | Using the public account token instead of the Secret API key, or identity verification is enabled. | Generate and use the Secret API key from Settings → Tokens. |
400 Bad Request | Missing name, or neither uid nor email present. | Ensure the event has a name and the pipeline maps user_id or an email trait. |
| Event delivered but no Experience fires | uid does not match the value passed to chmln.identify(). | Align the uid Signal sends with the one used in the in-app snippet. |
| Custom property missing in Chameleon | Property exceeds 768 bytes, or was not mapped. | Shorten the value and confirm the mapping exists in the blueprint. |