WooCommerce Stripe Link Not Autofilling Checkout Block Fix

WooCommerce Stripe Link not autofilling in the Checkout Block? Here is why saved cards never appear and the exact fix for the Payment Element mount.
WooCommerceStripeCheckout Block
June 7, 20266 min read1089 words

The Problem

A client reported that returning customers were typing their card details again. Stripe Link was enabled, the Express Checkout button was rendering on the cart page, but the Checkout Block at /checkout showed an empty card field with no Link prompt and no saved cards. No console errors. The Stripe gateway logs showed payment_intent creation succeeding, then a fresh card entry every time.

I ran into this on a WooCommerce 10.9 store running the official Stripe gateway 9.4 on WordPress 7.1. The store had switched from the legacy shortcode checkout to the Checkout Block three weeks before. Apple Pay worked. Express Checkout from the cart worked. Saved cards in My Account worked. The Checkout Block itself silently dropped Link.

The clue was in the network tab. The elements/create request from the block was firing with paymentMethodTypes: ["card"] and no customer field. Stripe's Payment Element will only show Link if it receives a customer id at mount and Link is included in the allowed types. The block was mounting the element before the WooCommerce Store API had returned the cart payload that contains the customer id.

Why It Happens

The Checkout Block uses the Store API to hydrate cart state, then dispatches a wc/store/payment action that the Stripe gateway listens for to mount its Payment Element. The race condition is real. If the Stripe gateway script registers its payment method before wc/store/cart finishes loading, it reads customer_id as 0 and falls back to a guest Payment Element with customer: null. Stripe treats a null customer as "no Link, no saved methods" and renders the plain card form.

The official gateway shipped a fix for this in 9.0 by deferring the mount until STORE_KEY resolved. What broke it again was a popular optimisation plugin a previous developer had installed that combined and minified scripts, which moved the Stripe gateway script ahead of the WooCommerce Blocks runtime in the bundle. The mount handler then fired before the Store API subscription was registered, and the deferred-mount logic gave up after a 500ms timeout because nothing answered.

There is also a server-side trap. The Stripe gateway only sets customer_id on the cart payload if the logged-in user has a Stripe customer record. If they have ordered before with a different gateway, the record does not exist yet. The block hydrates with customer_id: null, the mount fires, no Link.

The Stripe Payment Element with Link docs confirm both rules: the element needs customer at mount, and Link must be enabled in the Dashboard for the account and listed in paymentMethodTypes.

The Fix

Three changes in order. Excluding the gateway script from the optimiser is the one that unblocks 80% of cases.

Step 1: Exclude the Stripe block script from JS combining. In the optimisation plugin's settings, add this pattern to the exclusion list. Names vary (WP Rocket, LiteSpeed, Autoptimize, FlyingPress), but they all support an exclusion list:

woocommerce-gateway-stripe/build/upe-blocks
wc-stripe-blocks-checkout
wc-stripe-payment-request

After saving, hard reload the checkout page and confirm in DevTools that upe-blocks.js loads as its own request, not inlined. The mount handler now has time to subscribe before the Store API resolves.

Step 2: Ensure a Stripe customer exists at login. Add a tiny snippet to your child theme functions.php that creates the Stripe customer the first time a logged-in user lands on the checkout page. The official gateway does this on payment, which is too late for the block's initial render:

add_action( 'woocommerce_before_checkout_form_cart_notices', function () {
    if ( ! is_user_logged_in() ) {
        return;
    }
    $user_id = get_current_user_id();
    $stripe_customer_id = get_user_meta( $user_id, '_stripe_customer_id', true );

    if ( $stripe_customer_id ) {
        return;
    }

    if ( ! class_exists( 'WC_Stripe_Customer' ) ) {
        return;
    }

    $customer = new WC_Stripe_Customer( $user_id );
    $created = $customer->create_customer();

    if ( is_wp_error( $created ) ) {
        wc_get_logger()->error(
            'Stripe customer create failed: ' . $created->get_error_message(),
            array( 'source' => 'stripe-link-fix' )
        );
    }
} );

The customer id is now in user meta before the Store API hydrates the cart, so the cart payload carries the real id instead of null.

Step 3: Force Link into the allowed methods if the Dashboard toggle is on but the block forgets it. Some installs have Link enabled at the account level but the block still mounts without it because the gateway settings sync ran before the Dashboard flag flipped. Filter the payment method types the block requests:

add_filter( 'wc_stripe_upe_params', function ( $params ) {
    if ( ! is_array( $params ) ) {
        return $params;
    }

    $params['paymentMethodsConfig'] = $params['paymentMethodsConfig'] ?? array();
    $params['paymentMethodsConfig']['link'] = array(
        'isReusable' => true,
        'showSaveOption' => true,
    );

    return $params;
} );

Verify on a real customer. Log in as a user who has placed at least one prior order, clear the session, and load /checkout. Open DevTools, filter the network panel to stripe.com, and look at the elements/sessions request payload. The body should now include a customer field with a cus_ id and payment_method_types containing "link". The Payment Element should render the Link prompt at the top of the card field within 300ms.

If the prompt still does not appear, check the gateway debug log at WooCommerce → Status → Logs and filter by stripe. A customer_id mismatch warning means the user meta has a stale id from a deleted test account. Delete the _stripe_customer_id meta value and reload.

The Lesson

Stripe Link in the Checkout Block fails for one of three reasons: an optimiser plugin breaking the deferred mount, a missing Stripe customer record on the WordPress user, or a Dashboard sync that left Link out of the block's allowed methods. Fix all three at once and Link will show on first paint for every returning customer.

If your Checkout Block is silently dropping payment features and you cannot tell which plugin is the culprit, that is the kind of audit I run for stores every week. See my services. For a related Checkout Block bug, read WooCommerce Apple Pay not showing in Checkout Block.

Checkout Block dropping payment methods on your store? Get it fixed.

Back to blogStart a project