Amperity

Enterprise customer data platform using AI-driven identity resolution to unify customer records and power personalised experiences.

Datafly Signal talks to Amperity over three separate API surfaces, each driving a different capability:

CapabilityAmperity APIDirectionWhat it unlocks
Event ingestStreaming Ingest (/prof/events/)Signal → AmperityEvery Datafly event updates Amperity’s profile aggregations within seconds.
Profile enrichmentProfile API (/prof/profiles/)Signal ← AmperityServer-side lookup of visitor attributes (Persona, FavoriteBrand, LifetimeTier, …) attached to every event before delivery to downstream destinations.
Browser personalisationProfile API (via Signal)Browser ← Signalwindow.datafly.profile.amperity hydrated on page load for client-side personalisation. The Profile API token never touches the browser.

Prerequisites

Complete these steps in Amperity before configuring Signal.

Access your Amperity tenant

Log in to the Amperity dashboard at app.amperity.com. Two values you’ll need:

  • Tenant subdomain — the host in your dashboard URL (e.g. acme in https://acme.amperity.com). Used to build every API URL.
  • Tenant ID — the value Amperity expects in the Amperity-Tenant HTTP header. Usually the same as the subdomain, but in some multi-tenant demo/sandbox setups they differ.

Create a realtime event stream

Navigate to Sources > Streams and click Add Stream. Configure the routing expression to match the source value Datafly will send (e.g. routing on source == "DATAFLY" → your target event type).

After creation, copy the Event Stream ID — it’s prefixed esm- (e.g. esm-2VP6va3Zn).

⚠️

There is also a batch ingest path with IDs prefixed is-. Do not use this ID in Signal — it accepts events but does not drive realtime profile aggregation updates. Signal only supports the realtime esm- path.

Generate the Streaming Ingest API key

Go to Settings > Security > API Keys > Add API key. Select Streaming Ingest Write Access. Generate the JWT and copy the token immediately — it won’t be shown again.

For profile enrichment + browser personalisation you also need:

  • Profile Collection ID — from the dashboard collection you want to query, prefixed apc- (e.g. apc-vPsQheAm).
  • Profile API Key — a separate JWT with Profile Read Access scope. Must be distinct from the Streaming Ingest key; Amperity rejects cross-scope usage with 403.
  • Linking keys — the collection’s linking_keys array determines which identifiers Signal can use to resolve visitors. Add at least one of: device cookie (anonymous identifier), email_sha256, phone_sha256, or a customer-specified account_id. Ask your Amperity admin to add these if they aren’t configured.

Configuration

FieldTypeRequiredDescription
tenant_subdomainstringYesURL host component (e.g. acme for acme.amperity.com).
tenant_idstringYesValue sent as Amperity-Tenant header. Usually matches the subdomain.
api_keysecretYesStreaming Ingest JWT (write access).
event_stream_idstringYesRealtime stream identifier, prefixed esm-.
source_valuestringYesValue of the top-level source field on every event. Case-sensitive — must exactly match your stream’s routing expression or events are accepted (202) but silently dropped.
profile_api_keysecretNoProfile API JWT (read-only). Required for profile enrichment + personalisation.
profile_collection_idstringNoProfile collection to query, prefixed apc-. Required when Profile API Key is set.
linking_keystextarea (JSON)NoArray of {source, key, hash} specs driving how Signal resolves visitors against the Profile API. See Linking keys.
browser_attribute_allowliststring (CSV)NoComma-separated attribute names safe to expose to the browser. See Browser personalisation.

Signal Setup

Install the integration

Go to Integrations → Integration Library, find Amperity, click Install, and fill in all required fields with values from the prerequisites above.

Set linking keys (optional — for profile enrichment)

If you want Amperity profile attributes attached to every event (or exposed to the browser), configure the linking keys. See Linking keys below.

Set the browser allowlist (optional — for personalisation)

To expose profile attributes to window.datafly.profile.amperity in datafly.js, list them as a comma-separated string. Anything not in this list is stripped server-side before it reaches the browser.

Attach to a pipeline

From the pipeline page, add the Amperity integration. The blueprint (v1.8.0) provides 40+ flat global mappings shared across every vertical, plus vertical-specific event handlers so events flow through with minimal customisation.

Pick a vertical preset

The blueprint ships seven vertical presets — pick the one that matches your business and the event handlers will be pre-configured for that domain:

PresetEvent coverage
Retailpageview, view_item_list, view_item, add_to_cart, view_cart, begin_checkout, purchase. Accepts both GA4 (view_item) and legacy Segment (Product Viewed) names.
Travelflight_searched, hotel_searched, car_searched, flight_viewed, hotel_viewed, booking_started/completed/cancelled/modified, check_in_completed, check_out_completed, loyalty_points_earned/redeemed, review_submitted.
Finance & Bankingaccount_opened/closed, kyc_started/completed/failed, login_succeeded/failed, transaction_initiated/completed/failed, payment_made, transfer_completed, card_applied/approved/activated, loan_applied/approved/funded, statement_viewed.
B2B / SaaSsigned_up, logged_in/out, password_reset_requested, trial_started/converted/expired, subscription_started/upgraded/downgraded/cancelled/renewed, feature_used, invitation_sent/accepted, seat_added/removed, integration_connected.
MediaVideo lifecycle: video_playback_started/paused/resumed/completed, video_content_started/completed/milestone, video_ad_started/completed/skipped. Audio + podcast: audio_playback_*, podcast_subscribed.
Gaminggame_started/ended, level_started/completed/failed, achievement_unlocked, tutorial_*, item_purchased/equipped, currency_earned/spent, friend_invited, match_started/completed, leaderboard_viewed.
Publishingarticle_viewed/read/shared/bookmarked, category_viewed, search_performed, newsletter_subscribed/unsubscribed, paywall_viewed, subscription_started/cancelled, comment_posted, author_followed.

All presets share the same global mappings (identity, network, locale, page, session, campaign, geo, vendor IDs, consent), so the only difference between them is the event handlers and the property names they pull off event.properties.*. Unmapped events still pass through (the blueprint defaults to pass_through), so you can ship custom event names without changing the blueprint.

Event ingest (Streaming Ingest)

Every event Signal processes is forwarded to the realtime /prof/events/{event_stream_id} endpoint:

POST https://{tenant_subdomain}.amperity.com/prof/events/{event_stream_id}
Amperity-Tenant: {tenant_id}
Authorization: Bearer {api_key}
Content-Type: application/json
 
{
  "source": "{source_value}",
  "type": "view_item_list",
  "cookieid": "anon_abc123",
  "ip_address": "...",
  "user_agent": "...",
  "timestamp": "2026-04-17T15:37:10.484Z",
  "email": "...",
  "amperity_id": "...",
  ...30+ flat attributes from the blueprint
}

Datafly sends flat payloads by default — Amperity accepts nested objects too, but flat means customers don’t need to write flatten scripts on the Amperity side. The full Amperity field mapping is browsable in the Management UI under the Amperity integration’s blueprint editor.

Server-side profile enrichment

When profile_api_key + profile_collection_id are set, Signal performs partner enrichment on every event:

Resolve the visitor

Using the configured linking keys, Signal issues Profile API lookups until one matches. Successful resolutions are cached server-side so subsequent events skip the call; failed resolutions are dampened to keep partner API traffic bounded.

Fetch profile attributes

Given the resolved amperity_id, Signal calls GET /prof/profiles/{collection_id}/{amperity_id} and receives the full attribute map.

Attach to the event

Attributes are attached to the event as partner_attrs.amperity and are accessible to every downstream blueprint via source paths like:

global:
  mappings:
    - source: partner_attrs.amperity.Persona
      target: user_persona
    - source: partner_attrs.amperity.LifetimeTier
      target: user_tier

This lets Meta CAPI, GA4, TikTok, etc. receive enriched Amperity attributes on every event without each integration doing its own Amperity lookup.

Context-sensitive personalisation

Amperity can return different attribute values depending on the visitor’s current context (which product category they’re on, what’s in their cart, etc.). Enable it by:

  1. Setting Enable Context-Sensitive Personalisation on the integration.
  2. Configuring Personalisation Context Mappings — a JSON array of {source, target} pairs describing what context values Signal forwards to Amperity on each call.
[
  {"source": "properties.category", "target": "pageCategory"},
  {"source": "properties.value",    "target": "cartValue"},
  {"source": "context.page.path",   "target": "pagePath"},
  {"source": "partner_attrs.amperity.LifetimeTier", "target": "tierHint"}
]

How it works

  • Server-side only. The browser never passes context values — they’re computed from the current event using Signal’s standard path syntax (context.*, properties.*, partner_attrs.*, flat event fields).
  • Amperity is configured to interpret the context keys you send (e.g. configure attribute logic in Amperity that uses pageCategory).
  • Result merges into partner_attrs.amperity_personalized and — if the browser allowlist is configured — flows through to window.datafly.profile.amperity.
  • Cache key includes a hash of the context values, so different page/cart states produce independent cache entries (2-minute TTL). Same context → same cached response → no extra Profile API call.

Use personalisation sparingly — every unique context hash is a cache miss and a Profile API call. Good targets: small-cardinality values like page category or LTV tier. Avoid URL parameters, timestamps, or other high-entropy fields.

Browser personalisation

Datafly.js auto-hydrates window.datafly.profile.amperity with the allowlisted attribute subset on page load — no Profile API token touches the browser, no extra HTTP calls from the page.

Flow

  1. The visitor’s attributes are resolved server-side via the Amperity Profile API and filtered through browser_attribute_allowlist.
  2. The filtered profile is made available to Datafly.js on init.
  3. Browser code reads datafly.profile.amperity after datafly.onProfileReady() resolves.

Page-side usage

datafly.init({
  pipelineKey: '...',
  endpoint: 'https://collect.example.com',
  // Baked in by the Collector tab when Amperity personalisation is enabled:
  enrich: {
    endpoint: 'https://id.example.com',
    providers: ['amperity'],
  },
});
 
await datafly.onProfileReady();
const persona = datafly.profile.amperity?.Persona;
if (persona === 'Value Hunter') {
  document.querySelector('#hero').dataset.variant = 'promo';
}
 
// After a user logs in / identifies, you can refresh to pick up richer attributes:
datafly.identify('user-123', { email: 'alice@example.com' });
await datafly.refreshProfile();

What the browser can and cannot see

  • Only attributes in browser_attribute_allowlist — configured server-side, not overridable by page code.
  • Empty-attributes response (HTTP 200 with attributes: {}) for first-touch visitors with no resolved profile.
  • Never the Profile API token.
  • Never the raw Amperity response — always filtered server-side first.

Identity

Signal sends the following identifiers to Amperity on every event (subject to which linking_keys are configured on the Amperity side):

FieldSourceNotes
cookieidDatafly anonymous identifierStable per-browser identifier. Always present.
user_iddatafly.identify() user IDPresent after the visitor logs in or is identified.
emailtraits.emailPlain text by default; can be hashed when matching against email_sha256 linking keys.
phonetraits.phonePlain text by default; can be hashed when matching against phone_sha256 linking keys.
ip_addressrequest IPForwarded from the original browser request.
user_agentrequest user-agentForwarded from the original browser request.

Call datafly.identify() when a user logs in or submits a form to maximise the identifiers available for resolution:

datafly.identify("user-123", {
  email: "jane.doe@example.com",
  phone: "+44 7700 900123"
});

Every event carries the visitor’s full consent state to Amperity in a nested consent field. This is unconditional — Datafly always forwards consent, there is no option to strip it. Amperity uses it to suppress or downgrade processing per visitor in line with the permission they granted.

Shape sent on every event:

{
  "consent": {
    "analytics": true,
    "marketing": false,
    "functional": true,
    "categories": {
      "C0001": true,
      "C0002": false,
      "ad_personalization": false
    },
    "google": {
      "ad_storage": "denied",
      "ad_user_data": "denied",
      "ad_personalization": "denied",
      "analytics_storage": "granted"
    }
  }
}

Why it’s nested, not flat

Every CMP has a different taxonomy — OneTrust uses C0001..C0004, CookieYes uses analytics/marketing/functional, TrustArc uses custom codes, plus Google Consent Mode v2 has its own four-parameter shape. Flattening to specific field names would lock the blueprint to one CMP vendor. Nesting preserves the full consent context verbatim, and Amperity-side extractors pick out whatever categories the customer cares about.

What’s included

  • consent.analytics / marketing / functional — Datafly’s canonical booleans. Present when the CMP exposes these as top-level concepts.
  • consent.categories — arbitrary CMP category codes (the full context.consent.categories map).
  • consent.google — Google Consent Mode v2 values when available (ad_storage, analytics_storage, ad_user_data, ad_personalization).

Visitors with no CMP interaction have the field absent or partial — Amperity should treat absence as “no consent given” per the customer’s usual defaults.

Linking keys

Amperity collections maintain a linking_keys allowlist controlling which identifiers Datafly can pass to the Profile API. Configure Signal to match:

[
  {"source": "email", "key": "email_sha256", "hash": "sha256"},
  {"source": "canonical_id", "key": "device_cookie"},
  {"source": "user_id", "key": "customer_id"}
]

Each entry:

  • source — where Signal pulls the value from on the Datafly side. One of: canonical_id (the device cookie / anonymous identifier), anonymous_id, user_id, email, phone.
  • key — the name that matches an entry in your Amperity collection’s linking_keys. Amperity rejects lookups against keys not in that list.
  • hash — optional. sha256 applies lowercased-trimmed SHA-256 to the source value before sending. Use this for email/phone when your Amperity collection uses hashed PII linking keys.

Resolution strategy: Signal tries each entry in order and returns the first match. If a source field is empty on a visitor (e.g. anonymous user with no email), that entry is skipped.

If the collection’s linking_keys array is empty, Profile API lookups will always return 404. Production customers typically configure at least email_sha256 and a device cookie identifier.

Event name mappings

The v1.8.0 blueprint’s Retail preset handles both GA4-style and Segment-style event names that datafly.js might emit. Other vertical presets follow GA4-style names from the corresponding event spec:

Datafly.js eventAmperity type field
pagepageview
view_item / Product Viewedview_item
view_item_list / Product List Viewedview_item_list
add_to_cart / Product Addedadd_to_cart
Product Removedremove_from_cart
view_cart / Cart Viewedview_cart
begin_checkout / Checkout Startedbegin_checkout
purchase / Order Completedpurchase

Unmapped events pass through (this is a CDP) — Amperity’s routing expression decides what to ingest vs. route to _unknown.

Verify it’s working

Event ingest

  1. Fire a test event from your website or Signal’s event API.
  2. In Signal, open Live Events and click the event — the Vendor Request tab should show POST https://{tenant_subdomain}.amperity.com/prof/events/{event_stream_id} with status 202.
  3. In Amperity, navigate to your stream’s event inspector. Within ~5 seconds the event appears; within ~15 seconds the profile’s updated_at and any configured aggregations update.

Profile enrichment

  1. Ensure Profile API creds + linking keys are set.
  2. Fire an event from a visitor whose identifier matches an existing profile (e.g. send an identify with an email that’s in your Amperity collection).
  3. Inspect the next outbound event — its Transformed Event tab should show partner_attrs.amperity populated.

Browser personalisation

  1. Ensure browser_attribute_allowlist is set and datafly.js is built with enrich config.
  2. Open browser devtools → Network tab.
  3. Load the page. You should see GET /v1/enrich?provider=amperity fire after init, returning {provider: "amperity", attributes: {...}} with only the allowlisted keys.
  4. In the console, window.datafly.profile.amperity should match the response’s attributes.

Troubleshooting

SymptomLikely causeFix
Events return 202 but don’t appear in AmperityWrong source_value — event silently routed to _unknownCheck your stream’s routing expression in Amperity and match exactly (case-sensitive).
dial tcp: no such host on {tenant_subdomain}.amperity.comtenant_subdomain is wrong — it’s the URL host, not the header valueUse the subdomain portion of your Amperity dashboard URL.
401 / 403 on event POSTStreaming Ingest JWT expired or wrong scopeRegenerate under Settings > Security > API Keys with Streaming Ingest Write Access.
403 on Profile API GETUsing the Streaming Ingest JWT instead of the Profile API JWTThey’re distinct tokens with distinct scopes — generate a new one with Profile Read Access.
Profile lookups always 404Collection’s linking_keys doesn’t include any key Signal is sendingAsk your Amperity admin to add email_sha256 / device cookie / etc. to the collection’s linking_keys.
partner_attrs.amperity never appears on eventsVisitor not resolved OR Profile API creds missing OR no linking keys configuredCheck Signal’s Live Events for partner resolve failed warnings.
window.datafly.profile.amperity is emptyNo browser_attribute_allowlist configured (empty = nothing exposed)Add attribute names as CSV. Anything not in the list is stripped server-side before reaching the browser.

See also

  • Zeotap — alternative CDP with identity resolution
  • LiveRamp — RampID-based identity resolution
  • Event specs — canonical Datafly event schema

Visit Amperity documentation for full API reference and Streaming Ingest configuration details.