Checkout Analytics
Capture how each checkout was rendered to the buyer — which AVS fields were shown, which surface and layout were used — so you can correlate UX choices with conversion, auth, and chargeback rates.
Checkout Analytics
Every checkout session records four metadata fields that describe how the checkout was presented to the buyer. These fields live on the checkout_session row in the billing API and let you correlate UX choices (AVS configuration, layout, surface) with downstream outcomes — auth rate, conversion, chargeback rate.
What Gets Recorded
| Column | Type | Records |
|---|---|---|
avs_check | boolean (default false) | Were any AVS fields shown to the buyer? |
avs_config | jsonb (nullable) | The resolved exposure — which fields were actually visible for this buyer's country (booleans only, not the raw rules) |
checkout_type | string (nullable) | 'standard_checkout' (hosted /secure page) or 'embedded_checkout' (FloPayCheckout inline on a partner site) |
checkout_layout | string (nullable) | 'default_layout', 'buttons_layout', or 'custom_layout' |
All four columns are nullable (or default false). Older sessions and non-Stripe flows leave them empty — your existing analytics queries continue to work unchanged.
avs_config — resolved exposure, not raw rules
avs_config records the fields the buyer actually saw, not the rule that decided it. If the SDK was configured with enableAVS={{ address_line_1: ['US','CA'] }} and the buyer is in Germany, avs_config.address_line_1 is false — to that buyer the field didn't exist.
This makes downstream queries simple:
Example row:
How the Fields Get Populated
The SDK populates all four fields automatically. There are two write paths:
- At session creation — when you use
FloPayCheckout'screateSessionprop orcreateCheckoutSession, the analytics fields are sent in the create body alongside items, account data, etc. - At process time — when the buyer submits payment, the
/processrequest also carries the analytics fields. The backend writes them with an atomicUPDATE … WHERE column IS NULL(andWHERE avs_check = falsefor the boolean), so concurrent process calls cannot race or overwrite each other.
If both paths set a value, the first writer wins — the create-time value is preserved because the conditional update only runs when the column is still null (or false for avs_check).
Independent Session Creation
When a partner creates the checkout session server-to-server (their backend calls POST /v1/checkouts/sessions and only hands the resulting sessionId to the SDK), the analytics fields can come from one of two places:
Option A — Let the SDK populate at process time (zero changes)
Don't include analytics fields in the create body. The SDK still sends them on /process, and the conditional update writes them to the row before payment is finalized.
This is the recommended default for most consumers. As long as the partner is on @flopay/react@0.5.0 or later, the analytics columns will be populated for every completed payment without any backend changes.
Option B — Set them at session creation
Pass the four fields in the create body to populate analytics on every session, including abandoned ones (where /process is never called).
The DTO validates these fields:
checkoutTypemust be'standard_checkout'or'embedded_checkout'checkoutLayoutmust be'default_layout','buttons_layout', or'custom_layout'avsConfigmust be an objectavsCheckmust be a boolean
Invalid values fail fast with a 400.
Mixing the two is safe. If the create body sets a value, the SDK's later /process write becomes a no-op — setAnalyticsIfUnset only writes when the column is still null. Partners can opt in to early population without breaking SDK-driven population.
What you should NOT do
- Don't send the raw
enableAVSconfig. The SDK'senableAVSprop accepts per-country rules likeaddress_line_1: ['US','CA']. Those rules are authoring state —avs_configrecords exposure. If you setavs_configserver-side, resolve the rules against the buyer's country yourself first. - Don't send
avsCheck: truewhile sending anavsConfigwhere every field isfalse. These will look inconsistent in queries. - Don't backfill on completed sessions.
setAnalyticsIfUnsetis the only safe writer; manualUPDATEs can overwrite values that downstream consumers have already read.
Suggested Analyses
AVS impact on auth rate
Marginal value of street address (US only)
Layout conversion
Standard vs embedded surface
SDK Reference
The four analytics fields are part of the public typings on @flopay/shared:
InlineSessionParams— forFloPayCheckout'screateSessionCreateSessionParams— forcreateCheckoutSessionProcessPaymentParams— for the/processrequestAVSFieldConfig— the shape ofavsConfig
Backwards Compatibility
- All four columns are nullable (or default
false). Existing rows are unaffected. - Older SDK clients (pre-0.5.0) send neither path — those rows just stay
NULL. - Non-Stripe flows (Recurly, Chargebee) don't populate these fields today.
- Partner integrations that don't upgrade the SDK can still populate analytics manually via Option B.