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 a 401 once 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 same uid so Chameleon attaches them to the right profile.

Configuration

FieldRequiredDescription
Account Secret (Secret API Key)YesYour Chameleon Secret API key, sent as the X-Account-Secret header.

Configure in Signal

  1. In the Signal dashboard, open Integrations and add Chameleon.
  2. Paste your Account Secret (Secret API Key).
  3. Attach the Chameleon blueprint to a pipeline. The default Product / SaaS preset maps page, Signed Up, Logged In, Feature Used, Trial Started, and Order Completed.
  4. 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/json

A 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 fieldChameleon fieldNotes
user_iduidYour backend user id. Should match the uid passed to chmln.identify(). Required by the default preset.
email (trait)emailUsed 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 eventChameleon name
pagePage Viewed
Signed UpSigned Up
Logged InLogged In
Feature UsedFeature Used
Trial StartedTrial Started
Order CompletedOrder 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

  1. Trigger an event on your site (for example, sign up or use a tracked feature) with a known uid.
  2. In Chameleon, open the matching User Profile and confirm the event appears in the activity timeline within a few seconds.
  3. Build an Experience targeted on that event and confirm it triggers for the user.
  4. In Signal’s Event Debugger, confirm the outbound request returned a 200 with an event.id in the response.

Troubleshooting

SymptomCauseFix
401 UnauthorizedUsing 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 RequestMissing 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 firesuid 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 ChameleonProperty exceeds 768 bytes, or was not mapped.Shorten the value and confirm the mapping exists in the blueprint.