Pay Monthly

See the component in action in the live demo, which runs two of them against a stage checkout configuration.

Advertise a FlexPay monthly payment offer on the pages that come before checkout — a product detail page, a category listing, or a cart. The <flexpay-pay-monthly> component renders a single line,

Pay Monthly from $83/mo ⓘ with flexpay

and its ⓘ button opens FlexPay's information modal, where the customer can see the terms and what their installments would look like.

It is the same offer line the Checkout component shows when FlexPay is enabled, and it reads the same checkout configuration, so what you advertise on a product page is what checkout goes on to offer. It cannot take a payment: there is no payment session behind it, and nothing the customer does in it charges them. Use it to make financing visible early, then let them pay through <checkout-session> as usual.

Step 1: Get your checkout configuration ID (Once)

Ask your account manager for the checkout configuration ID to use, and confirm FlexPay is enabled on it. It is the same kind of ID you already pass when creating a payment session, and the component resolves the FlexPay account and financing limits from it at runtime — so nothing about your FlexPay account is pasted into your page, and moving to live FlexPay is a change on your ClientLoop configuration, not a change to your markup.

This component needs no server-side call: there is no session to create, so nothing here uses your API key.

Step 2: Load the checkout script (Client)

<flexpay-pay-monthly> ships in the checkout bundle. Load it ideally in the <head> of your page. If the page already loads the checkout script for <checkout-session>, you are done — do not load it twice.

<script type="module" src="https://js.clientloop.com/checkout.iife.js"></script>

Step 3: Render the component (Client)

Place it wherever the price is shown, and pass that price as amount.

<flexpay-pay-monthly
  checkout-configuration-id="CHECKOUT_CONFIGURATION_ID"
  amount="999.00"
  currency="USD"
></flexpay-pay-monthly>

By default the component reads your configuration from ClientLoop production. To test your integration against the ClientLoop staging environment, set the optional env attribute to stage:

<flexpay-pay-monthly
  checkout-configuration-id="CHECKOUT_CONFIGURATION_ID"
  amount="999.00"
  env="stage"
></flexpay-pay-monthly>

Omit env (or set it to prod) for production.

Try it against stage

This is the exact markup behind the live demo — a stage checkout configuration with FlexPay enabled. Paste it into a page to see a real offer before you have a configuration ID of your own:

<script
  type="module"
  src="https://js.stage.clientloop.com/checkout.iife.js"
></script>

<flexpay-pay-monthly
  checkout-configuration-id="38wrAJLeirEkhV4uiwp1h3LTE3o"
  env="stage"
  amount="999.00"
  currency="USD"
></flexpay-pay-monthly>

Note that the stage graph only answers pages served from a known ClientLoop origin, so this snippet renders on localhost and on the ClientLoop docs sites but not from an arbitrary host. Ask your account manager to have your own origin added while you integrate.

Attributes

Attribute Required Default Purpose
checkout-configuration-id yes — The checkout configuration to read the FlexPay account and limits from.
amount yes — The price to quote against, in dollars — "999.00", not cents.
currency no USD USD or CAD. FlexPay supports no other currencies.
env no prod ClientLoop environment the configuration is read from — stage to test.
locale no en-US, or en-CA for CAD The locale FlexPay formats its wording and currency in, e.g. fr-CA.
theme no checkout Theme the line is styled with, matching <checkout-session> by default.
theme-tokens no — Your own colours as daisyUI design tokens — see Using your own colours.
spinner no built-in Your own loading spinner: inline SVG markup, or an image URL.
suppress-spinner no false Show nothing while an offer is being priced, rather than a spinner.
debug no false Logs configuration and offer activity to the browser console.

Step 4: Keep a cart in step (Client)

On a cart, the total moves as items are added and removed. Assign amount and the offer is re-quoted:

<flexpay-pay-monthly
  id="cart-offer"
  checkout-configuration-id="CHECKOUT_CONFIGURATION_ID"
  amount="1499.00"
></flexpay-pay-monthly>

<script>
  const offer = document.getElementById('cart-offer');

  // Call this whenever your cart total changes.
  function cartTotalChanged(total) {
    offer.amount = total.toFixed(2);
  }
</script>

The previous monthly figure disappears while FlexPay prices the new total, so the line never shows a monthly amount that does not match the total next to it. It reappears as soon as the new offer arrives.

Multiple offers on one page

A category or search-results page can hold one <flexpay-pay-monthly> per item — give each its own amount. The configuration lookup, the FlexPay script, its setup and the offer request are all shared across every widget on the page, so twenty products cost the same one lookup and one offer request as a single product.

Every widget on a page must use the same checkout-configuration-id, currency, locale and env: the first one to render sets them for the page.

When nothing renders

The component renders nothing at all unless an offer is available. That is deliberate — an unavailable offer leaves your page exactly as it was, with no empty space or placeholder to design around. Expect an empty result when:

  • the amount is outside the range your configuration will finance,
  • FlexPay declines to quote for the visitor,
  • the checkout configuration ID is wrong, disabled, or has no FlexPay enabled,
  • you are pointed at the wrong env for that configuration ID, or
  • the currency is not USD or CAD.

Add debug while integrating to see what the component is doing in the console; it reports which of these applied. Because the line appears only once an offer arrives, give it a container that can collapse to nothing rather than a fixed-height slot.

While the offer is loading

The component shows a small spinner where the line will go — when the page first loads, and again whenever you change amount and the previous figure is withdrawn. It disappears as soon as the offer arrives, and after about eight seconds if none does; FlexPay reports "no offer" by staying silent, so a spinner waiting on that would never stop.

If offers are often unavailable on your pages, the spinner will appear and then vanish with nothing in between, which can read worse than the line simply arriving late. Turn it off with suppress-spinner:

<flexpay-pay-monthly
  checkout-configuration-id="CHECKOUT_CONFIGURATION_ID"
  amount="999.00"
  suppress-spinner
></flexpay-pay-monthly>

Or supply your own with spinner — inline SVG markup, or the URL of an image. An inline SVG is preferable: it scales with your text and can inherit its colour, and there is no second request before it appears.

<flexpay-pay-monthly
  checkout-configuration-id="CHECKOUT_CONFIGURATION_ID"
  amount="999.00"
  spinner="<svg viewBox='0 0 24 24'>…</svg>"
></flexpay-pay-monthly>

The markup is inserted as-is, so pass only spinner markup you control.

Using your own colours

The line has a transparent background and takes its wording colour from your page, which is usually all you need. When it isn't — a brand palette, or colours your CMS resolves at runtime — pass theme-tokens, a map of daisyUI design tokens. It behaves exactly as it does on the Apply component:

  • Overlay — with theme set, your tokens override just those parts of it.
  • Replace — without theme, your tokens are the theme. Supply a complete set; anything you leave out is simply absent.
<flexpay-pay-monthly
  checkout-configuration-id="CHECKOUT_CONFIGURATION_ID"
  amount="999.00"
  theme="checkout"
  theme-tokens='{"--color-base-content":"#e5e5e5"}'
></flexpay-pay-monthly>

Set it as a property when the values come from an API:

document.querySelector('flexpay-pay-monthly').themeTokens = {
  '--color-base-content': '#e5e5e5',
};

Passing tokens turns off the page-colour inheritance described below, since the point of passing them is to say what the colours are — use --color-base-content for the wording. The monthly figure and the FlexPay logo stay FlexPay green either way; those are not yours to theme.

How it looks on your page

The line has a transparent background and takes its wording colour from your page, so it reads on a dark site as well as a light one and sits inline with your own text. The monthly figure and the FlexPay logo are always FlexPay green. It needs roughly 320px to stay on one line; below that it wraps.

Note that the financing range comes from your ClientLoop configuration, not just from FlexPay — so a product priced above your configured ceiling advertises nothing, exactly as checkout would decline to offer FlexPay for it.

Listening for the offer

<flexpay-pay-monthly> emits a DOM CustomEvent each time FlexPay prices an offer for it. It bubbles and is composed, so a single listener on the element sees it.

Event When it fires
flexpay-pay-monthly-offer-changed FlexPay returned a new monthly amount for this widget.

The event's detail is the monthly amount as a plain string of dollars (for example "83"), or an empty string when the offer was withdrawn.

<script>
  const offer = document.querySelector('flexpay-pay-monthly');

  offer.addEventListener('flexpay-pay-monthly-offer-changed', (event) => {
    analytics.track('pay_monthly_offer_shown', { monthly: event.detail });
  });
</script>