Checkout metadata
For engineers reading payment webhooks and matching them back to funnel sessions. You'll have the canonical field list and the per-provider object names that carry it. You need access to your payment provider's dashboard or API to inspect the objects.
Zellify attaches a single, well-defined metadata object to every payment object it creates. The same set of fields goes on the Customer, the Subscription, the Checkout Session, the Transaction, the Order — whatever the provider supports. There is no per-object subset: if you read the metadata field on any Zellify-created payment object, you will see the same shape.
Canonical fields#
Every Zellify-created payment object carries these fields. Some are conditional — the field is omitted when the value is not available, rather than set to null.
| Field | Type | When set |
|---|---|---|
app_user_id | string (UUID) | Always. The funnel session identifier — the same value sent as context.appUserId in the Registration webhook. See app_user_id. |
organization_id | string (UUID) | Always. The Zellify organization that owns the funnel. |
funnel_id | string | Always. The funnel where the checkout happened. |
campaign_id | string | Always. The campaign link the visitor used to reach the funnel. |
experiment_id | string | Only when the campaign targets an A/B experiment. |
fbp | string | Only when the visitor has a Meta _fbp browser cookie. |
fbc | string | Only when the visitor came from a Meta ad click and has an _fbc value. |
That is the entire payload. Zellify does not vary the field list by object type, by payment mode, or by provider.
Where it lives per provider#
The fields above are identical across providers. What differs is the property name on the object (metadata vs custom_data) and which objects carry it.
Stripe#
Property name on the object: metadata
Attached to every Stripe object Zellify creates during a checkout:
Customer.metadataCheckout Session.metadataSubscription.metadata(for subscription mode)Subscription Schedulephases — each phase carries the samemetadata(used for multi-phase pricing)Invoice.metadata(for upsells, which are charged via invoice)
Read it from the primary object in the webhook event: the session for checkout.session.completed, the subscription or invoice for invoice.paid, etc. See Payment events for the full event matrix.
The Stripe Customer's email is on the Customer object's top-level email field, not in metadata.
Paddle#
Property name on the object: custom_data
Attached to:
Customer.custom_dataTransaction.custom_data
Paddle subscriptions are created from the originating transaction, so the transaction's custom_data is what reaches your subscription webhook events.
Solidgate#
Property name on the object: metadata (called order_metadata when Zellify sends it).
Attached to:
Order.metadataSubscription.metadata(carried over from the order on subscription products)
The Solidgate payment intent also carries two top-level customer-identity fields, separate from metadata:
customer_email— the user's emailcustomer_account_id— set to the same value asapp_user_id, used to link the Solidgate customer record to the Zellify funnel session
Reading metadata in webhooks#
The metadata lives on the primary object inside the event, not at the event root. If the field is missing, the event likely refers to an object Zellify did not create (manual dashboard action, direct API call, refund created in Stripe UI). Handle that case defensively rather than assuming app_user_id is always present.
For Paddle, replace metadata with custom_data.