Using Existing Webhooks

If you already provision accounts from Stripe or Paddle webhooks, here is what changes when you add Zellify.

The Problem

You already have a working system that creates user accounts and grants entitlements based on Stripe or Paddle webhook events. You are now adding Zellify as a web acquisition channel. You want to know what changes, what stays the same, and how to connect the Zellify funnel experience to your existing provisioning flow.


What Stays the Same

Your existing webhook handlers continue to work exactly as before. Zellify does not interfere with your webhook setup. All payments flow directly to your Stripe or Paddle account, and your existing webhook endpoints receive the same events they always have.

If you currently provision accounts based on events like checkout.session.completed (Stripe) or transaction.completed (Paddle), that logic does not need to change.


What Changes

When a purchase originates from a Zellify funnel, the Stripe Customer/Subscription or Paddle Customer/Transaction will have additional metadata that Zellify attaches at checkout:

  • app_user_id — a unique identifier for the funnel visitor

  • organization_id — the Zellify organization

  • funnel_id — which funnel the user went through

  • campaign_id — which campaign drove the user

  • experiment_id — which A/B test variant (if applicable)

  • fbp, fbc — Facebook attribution identifiers (if applicable)

This metadata is set on Stripe Customer and Subscription metadata and Paddle Customer and Transaction custom data.

Your existing handlers already receive the webhook payloads. The metadata is simply additional data on the customer and subscription/transaction objects. You can read it or ignore it — your existing logic will not break.


How to Use app_user_id

The most useful new field is app_user_id. This is a Zellify-generated identifier that is consistent across the payment provider metadata and the success page Deep Link Button.

If you add a Deep Link Button to your funnel's success page, it will interpolate the same app_user_id into the URL — whether that is a mobile deeplink or a web redirect. This gives you a way to connect the user who lands in your app or on your signup page to the payment event your webhook handler already processed.

If your current provisioning creates an account using email only:

You can continue using email. Zellify ensures the email collected in the funnel is set on the Stripe/Paddle customer, so your existing email-based matching will work.

However, consider also storing app_user_id from the metadata. It provides a deterministic link that does not depend on email matching and can be passed through the success page Deep Link Button to your app or web product.

If you want to start using app_user_id:

  1. Update your webhook handler to read app_user_id from the metadata/custom data on the customer or subscription/transaction object

  2. Store it alongside the user account in your database

  3. Add a Deep Link Button to your Zellify funnel's success page, configured to pass app_user_id to your app or web product

  4. When the user arrives at your product, use app_user_id to look up their account


What Zellify Handles

  • Creates customers in Stripe/Paddle with structured metadata (including app_user_id) before payment completes

  • Provides the Deep Link Button on the success page to route users to your product with app_user_id

  • Registers its own webhook listener for analytics only — this does not conflict with your existing webhooks


The Linking Key

app_user_id is the bridge between a Zellify funnel session, the payment event your webhook receives, and the user arriving at your product from the success page.

If you were previously provisioning accounts without Zellify, you likely matched on email alone. With Zellify, you now have app_user_id as an additional, deterministic identifier that flows from checkout to webhook to deeplink — all automatically.


Last updated