Overview
AppDNA can receive webhooks from billing, attribution and messaging providers. Each authenticated delivery is stored and converted into AppDNA’s canonical events withsource: "<provider>". RevenueCat has its own page:
RevenueCat.
Provider events count for revenue, not for activity. Provider events count for revenue, lifetime revenue and
attribution. They never count as sessions, active users, retention or billable MAU — those come only from the AppDNA SDK
running in your app. Purchases and renewals from a billing provider (RevenueCat, Adapty, Superwall) do count toward
MTPU (monthly tracked paying users), once per user after de-duplication with SDK purchases. Once a billing provider
reports a subscription, its renewals are counted from the provider only; the SDK’s device renewal for that subscription
adds no revenue.
How each provider counts
- One purchase, one count. When several sources report the same store transaction, AppDNA keeps one, by precedence RevenueCat > Adapty > Superwall > the AppDNA SDK > events you tracked yourself.
- Do not track canonical purchase or attribution event names yourself with
AppDNA.trackwhen the corresponding webhook is connected; use custom names for your own UI analytics. - Events from a messaging or attribution provider never trigger AppDNA journeys or e-mail automations. Billing-provider purchases do, like SDK purchases — except replayed events (deliveries stored before the provider’s mapping was enabled), which never trigger journeys or e-mail automations.
- When several attribution providers are connected, AppsFlyer > Adjust > Singular decides a user’s attribution.
Authentication and secrets
Each provider uses one of three mechanisms. The integration page shows the right controls.- Reveal, Copy and Rotate are owner-only. The Authorization value, or the tokenised URL, is masked on the integration page; only the organisation owner can reveal, copy or rotate it. Right after an admin connects an integration, the connect dialog shows the plain URL and, for the owner, the credential once. Rotating invalidates the old credential immediately — paste the new one into the provider.
- Superwall has no AppDNA-generated secret: paste Superwall’s signing secret (
whsec_…). It can be replaced, not removed. Signatures older than 5 minutes are rejected. - Failed authentication returns 401. The reason is logged on AppDNA’s side, never the secret.
- Disconnected integrations drop deliveries. While an integration is disconnected, authenticated deliveries are answered with 200 (so the provider does not retry for hours or disable the endpoint) and discarded. Reconnecting keeps the existing secret.
Pass the AppDNA user id to each provider
AppDNA links a provider event to your user through the id you pass toAppDNA.identify. Give each provider the same
id:
Events from a user the provider does not yet know are stored and counted under a pseudonymous placeholder, and are
linked to the user when a later event from the same provider carries the id.
Provider setup
Adapty (billing)
- In Adapty → Integrations → Webhooks, paste the AppDNA webhook URL into both the production and the sandbox
endpoint fields, and paste the same Authorization value
Bearer <secret>into both the production and the sandbox Authorization fields. Adapty’s verification request on Save succeeds. - Sandbox events (
environment: Sandbox) go to AppDNA’s sandbox dataset. - If you renamed Adapty event ids, enter them under Renamed event IDs on the integration page so AppDNA recognises them.
- Mapped events: subscription and trial starts →
purchase_completed+subscription_started; renewals and trial conversions →subscription_renewed; renewal cancellations →subscription_canceled; expirations →subscription_expired; billing issues →subscription_renewal_failed; refunds →purchase_refunded; one-time purchases →purchase_completed. - With
billingProvider: adapty, the AppDNA SDK keeps sending its device renewal and cancellation events; connect the Adapty webhook to add server-side renewal and refund data once its mapping is enabled — AppDNA then counts each event once.
Superwall (billing)
- In Superwall → Integrations → Webhooks, add the AppDNA webhook URL, then copy Superwall’s signing secret into AppDNA’s Webhook signing secret (owner).
- Mapped events: initial purchases →
purchase_completed(+subscription_startedfor subscriptions), renewals →subscription_renewed, cancellations →subscription_canceled, expirations →subscription_expired, billing issues →subscription_renewal_failed; any event with a negative price →purchase_refunded, and so is a cancellation withcancelReason: CUSTOMER_SUPPORT(Superwall’s refund carrier) — it becomespurchase_refunded(negative revenue), notsubscription_canceled. - Superwall sends no test webhooks. Sandbox events go to the sandbox dataset.
AppsFlyer Push API (attribution-only)
- In AppsFlyer → Integration → API access → Push API, set method POST, the AppDNA URL, token name
Authorizationand valueBearer <secret>. - Tick these fields:
event_type,appsflyer_id,customer_user_id,media_source,campaign,af_c_id,af_adset,af_ad,af_channel,install_time,is_retargeting,is_primary_attribution,campaign_type,event_revenue,event_revenue_currency,event_revenue_usd, theaf_cost_*fields,country_code,platform. - AppsFlyer’s “Send test” button gets 401 by design: AppsFlyer test messages carry no token. Test with a real install, or use a separate AppsFlyer app for test builds.
- AppsFlyer has no sandbox flag; every delivery counts as production.
Adjust server callbacks (attribution-only)
- Use the full URL from Reveal (it includes the token) as a global callback with method POST, and add the single-activity ad-revenue callback if you monetise with ads.
- Include these placeholders in the body:
activity_kind,created_at_milli,installed_at,environment,adid,idfa,idfv,gps_adid,os_name,app_id,store,country,event_token={event},event_name,revenue_float,currency,revenue_usd,tracker,tracker_name,network_name,campaign_name,adgroup_name,creative_name,is_organic,is_reattributed,match_type,partner_parameters, plus the ad-revenue placeholders. - Add the global callback parameter
appdna_user_idin your app (above). - Rotating issues a new URL — update it in Adjust.
Singular Internal BI postbacks (attribution-only)
- Use the full URL from Reveal (it includes the token) as the postback URL.
- Set the Singular custom user id to the AppDNA id. Deliveries whose
fraud_statusis notvalidare stored, not counted. - Rotating issues a new URL — update it in Singular.
CleverTap Webhooks channel (messaging)
- Create a webhook in CleverTap with method POST, the AppDNA URL, and on the Headers tab the key
Authorizationwith valueBearer <secret>. - The
appdna_eventconvention: a CleverTap webhook is a campaign call, not an event stream. To record a specific engagement event, add the key-valueappdna_eventto the webhook with one ofpush_delivered,push_tapped,email_sent,email_delivered,email_opened,email_clicked,email_bounced,email_unsubscribed,in_app_message_shown,in_app_message_clicked— for example on a Live-behaviour webhook triggered by “Notification Clicked”. Post Action webhooks recordpush_delivered; any other campaign webhook recordsmessaging_campaign_sentfor each targeted profile. Template tests (is_test) are stored, not counted.
Pushwoosh Event Streaming (messaging)
- In Pushwoosh → Event Streaming, add the AppDNA URL and set the Authorization value
Bearer <secret>. - Mapped events:
Push Delivered→push_delivered,Push Opened→push_tapped, e-mail events →email_*, in-app shows and clicks →in_app_message_shown/in_app_message_clicked. - Pushwoosh batches events: expect up to 1 hour of latency.

