GoCardlessDeveloper Docs
Create a sandbox account

GoCardless Components#

View as Markdown

GoCardless Components is a JavaScript library for setting up mandates inside your own checkout — the payer never leaves your site or app. GoCardless handles compliance, payer name verification, and form validation, while you keep full control over the surrounding experience.

Unlike the Drop-in Flow, which renders as a modal, Components embeds inline in your checkout and offers deeper styling control — with less build effort than fully Custom Payment Pages. Today, Components supports Bacs (UK) mandate creation only.

Best for:

  • Embedding mandate setup natively in your UI without redirecting customers away
  • Bacs-only flows where the primary action is setting up a Direct Debit mandate for recurring collection
  • Maintaining brand consistency through the full sign-up journey
  • Teams who want more UX control than Hosted Pages, with less build effort than a fully custom API integration

Out of the box:

  • Embedded UI mounted into any element on your page
  • Built-in form validation, error states, and retry behaviour
  • Prefill customer details from your existing flow
  • Compliant mandate authorisation flow

If you need to collect a payment alongside the mandate or support a non-Bacs scheme, consider Hosted Pages, Drop-in Flow, or Custom Payment Pages instead. SEPA Core support for Components is planned for a future release.

1. Setup#

You can skip to Implementation if you already have:

  • An access token with GoCardless Components enabled
  • A server with an endpoint capable of minting session tokens from that access token
  • A server endpoint capable of fulfilling billing requests via the GoCardless API

1.1. Getting an access token#

The library authenticates via a short-lived session token, minted server-side from a long-lived access token.

For merchants#

Go to the /developers/access-tokens in the GoCardless dashboard:

  1. Enter a name to identify this token
  2. Select Read-write access scope
  3. Turn "Enable GoCardless Components" ON for that token
  4. Provide the domain where you will use the component
  5. Click Create access token

For partner integrators#

Refer to the Partners page for detailed examples on how to mint a session token per merchant.

1.2. Setting up an endpoint to mint session tokens#

The library should never see your access token directly. Instead, your backend uses it to mint a short-lived session token, which is what gets passed to the library components. To do this, make the following request to GoCardless using the access token:

POST /session_tokens
Authorization: Bearer YOUR_ACCESS_TOKEN
 
{
    "session_tokens": {
        "policies": [
            "ui_components"
        ]
    }
}

This returns a response of the form:

{
  "session_tokens": {
    "id": "...",
    "token": "..."
  }
}

session_tokens.token is the value your sessionToken callback (see Configuring the Library) should resolve to.

Token rules#

  • Mint one session token per checkout, don't share it across customers or checkout sessions.
  • Don't cache it, always mint a fresh one from your sessionToken callback.
  • Tokens expire after 30 minutes absolute, or after 10 minutes idle. The idle timeout can't be observed or inferred.

If a request to the GoCardless API fails because the token has expired, the library automatically calls your sessionToken callback again and retries once, so your endpoint should be able to be called repeatedly throughout longer flows.

1.3. Setting up a fulfilment endpoint#

When a payer completes the Components checkout flow, a callback signals that the billing request is ready to fulfil. You are responsible for calling POST /billing_requests/{billing_request_id}/actions/fulfil from your server at that point.

See the API reference for full details.

Example fulfilment endpoint in Ruby:

require 'sinatra'
require 'gocardless_pro'
 
client = GoCardlessPro::Client.new(
  access_token: '<YOUR_ACCESS_TOKEN>',
  environment: :sandbox
)
 
def validate_session_token(session_token, billing_request_id)
  session_token_client = GoCardlessPro::Client.new(
    access_token: session_token,
    environment: :sandbox
  )
  session_token_client.billing_requests.get(billing_request_id)
end
 
def fulfil_billing_request(billing_request_id)
  client.billing_requests.fulfil(billing_request_id)
end
 
post '/fulfil-billing-request/:billing_request_id' do
  billing_request_id = params[:billing_request_id]
  session_token = request.env['HTTP_SESSION_TOKEN']
 
  begin
    validate_session_token(session_token, billing_request_id)
    fulfil_billing_request(billing_request_id)
  rescue GoCardlessPro::Error => e
    status e.code
    content_type :json
    { success: false, error: e.message }.to_json
  end
end

2. Implementation#

2.1. Add the library to your project#

Add the GoCardless Components library:

<script src="https://ui-components.gocardless.com/latest/index.js"></script>

Loading this script attaches GcComponents to the global window object — this is what you'll use in the next step to configure the library.

2.2. Configure the Library#

Initialise the library with GcComponents.init(...), passing the configuration:

const gc = GcComponents.init({
  environment: "sandbox",
  sessionToken: () => fetch("/your-backend/session-token").then((r) => r.text()),
  onEvent: (event) => logEvent(event),
  onError: (error) => logError(error),
});
PropertyDescriptionRequired
environmentThe environment in which you want to use Components (local, live, sandbox, live-staging or sandbox-staging).Yes
sessionTokenA callback returning a fresh session token (see Setting up an endpoint to mint session tokens)Yes
appearanceCustom appearance configuration, applied to every component (see Customisation)No
enableAnalyticsWhether to enable analytics tracking. Defaults to true.No
onEventCallback invoked for every public event emitted by a mounted component (see Handling errors and events)No
onErrorFallback error callback for any mounted component that doesn't define its own onErrorNo

2.3. Create a Billing Request Component#

Select a mount target#

Create a <div> where you want the component to appear:

<div id="gc-billing"></div>

Initialise component#

const gc = GcComponents.init({
  environment: "sandbox",
  sessionToken: () => fetch("/your-backend/session-token").then((r) => r.text()),
  onEvent: (event) => logEvent(event),
  onError: (error) => logError(error),
});
 
const brComponent = gc.createComponent("billing-request", {
  schemes: [GcComponents.Scheme.Bacs],
  onReadyToFulfil: (billingRequestId) => fulfil(billingRequestId),
  onError: (error) => console.error("Error: ", error),
});
 
brComponent.mount("#gc-billing");
PropertyDescriptionRequired
schemesThe payment schemes to enable, as an array (e.g. [Scheme.Bacs]); currently only bacs is supported, and it's used by default if omittedNo
creditorIdID of the creditor to create the billing request underNo
prefilledCustomerPrefills the customer/billing details form (see below)No
appearanceCustom appearance configuration, merged on top of the top-level appearanceNo
onReadyToFulfil(billingRequestId: string) => void — called once the customer has submitted everything needed to fulfil the billing requestYes
onError(error: GoCardlessError) => void — called on error, in addition to the event busNo

Billing Component Form

3. Testing#

Run through the checkout flow end to end and confirm you reach the confirmation screen without errors. Then verify the mandate was created via the GoCardless dashboard or API.

Successful DD

4. Customisation#

Pass an appearance object in your config to match Components to your brand:

Components can be customised to fit the UI of your page. This is done through the appearance object, either globally in GcComponents.init(...), or per-component, where it's merged on top of the global one.

const appearance = {
  backgroundColor: "#bfe6f2",
  inputBorderRadius: "0px",
  wrapperBorderRadius: "0",
};
 
const gc = GcComponents.init({
  environment: "sandbox",
  sessionToken: fetchSessionToken,
  appearance,
});
 
gc.createComponent("billing-request", {
  appearance: {
    buttonColor: "#004d40",
  },
}).mount("#gc-billing");

You can modify colours, fonts, borders, padding etc. and set customisation on particular element types. All unset variables fall back to GoCardless defaults.

Full default theme:

{
  backgroundColor: "#F9F9F9",
 
  bodyFontSize: "14px",
  bodyFontWeight: FontWeight.normal,
 
  buttonBorderRadius: "32px",
  buttonPadding: "8px 20px",
  buttonPrimaryColor: "#1f2937",
  buttonPrimaryHoverBackgroundColor: "#4b5563",
  buttonPrimaryHoverTextColor: "#f9fafb",
  buttonPrimaryTextColor: "#f9fafb",
  buttonSubmitTextContent: "Set up direct debit",
 
  captionFontSize: "12px",
  captionFontWeight: FontWeight.normal,
 
  checkboxBackgroundColor: "#1f2937",
  checkboxSize: "16px",
  checkboxTextColor: "#1f2937",
 
  dropdownFooterBackgroundColor: "#faf9f7",
  dropdownFooterBorderColor: "#dfddda",
  dropdownHoverBackgroundColor: "#1f2937",
  dropdownHoverTextColor: "#FFFFFF",
  dropdownPadding: "8px",
 
  formValidationErrorColor: "#C52F2F",
  formVerticalSpacing: "12px",
 
  headerFontWeight: FontWeight.medium,
 
  inputBackgroundColor: "#FFFFFF",
  borderColor: "#9ca3af",
  inputBorderRadius: "4px",
  inputPadding: "12px 16px",
  inputPlaceholderColor: "#6b7280",
  inputTextColor: "#1f2937",
 
  labelTextColor: "#4b5563",
 
  linkHoverTextColor: "#3a66b9",
  linkTextColor: "#0464ff",
 
  loadingSpinnerColor: "#1f2937",
  separatorColor: "#9ca3af",
 
  textColor: "#000000",
  textFontFamily: 'Inter, "Helvetica Neue", Helvetica, Arial, sans-serif',
 
  tagBackgroundColor: "#e5e7eb",
  tagBorderRadius: "4px",
  tagPadding: "0 4px",
  tagTextColor: "#1f2937",
 
  wrapperBorderColor: "#9ca3af",
  wrapperBorderRadius: "8px",
  wrapperBorderWidth: "1px",
  wrapperMargin: "16px",
}

5. Handling errors and events#

Each component's public events are forwarded to the single top-level onEvent callback.

Errors are reported via onError, either on the component config or as a top-level fallback in GcComponents.init(...).

5.1 Troubleshooting errors#

Errors are reported as a GoCardlessError object of the following shape:

{
  code: 401,
  message: "Authentication failed. Please check your configuration.",
  isUnrecoverable: true,
  type: "authentication"
}
  • code — an HTTP-style status code
  • message — a human-readable description
  • isUnrecoverable — whether the checkout flow can continue after this error, or must be restarted
  • type / requestId / errors — optional, populated for errors returned by the GoCardless API

5.2 Common errors#

  • Billing request creation failed — the creation of a new billing request failed. Your session token may have expired or be invalid.
  • Scheme not supported — you have attempted to use a scheme that Components does not currently support. Ensure schemes only contains values from the enum Scheme.
  • HTML element not found — the library was unable to find the element in which to embed the component using your provided target selector. Ensure your selector is valid and present in the DOM before calling init(...).

5.3 Session token expiry#

If a request to the GoCardless API fails because the session token has expired, the library automatically calls your sessionToken callback again to mint a fresh token and retries the request once. If the retry also fails, the error is marked as unrecoverable and the component will prompt the customer to restart the flow.

5.4 Checkout errors#

When an error occurs during the flow, GoCardless renders an error screen and calls your onError callback with a GoCardlessError object:

{
  "type": "authentication",
  "message": "Authentication failed. Please check your configuration",
  "metadata": {
    "subType": "invalid_api_usage",
    "requestId": "1f6f8649-6e40-4b50-936b-a8924dc7d2cb",
    "statusCode": "401"
  },
  "isUnrecoverableError": false
}
FieldDescription
typeError type
messageDetailed error message
metadatasubType, requestId, statusCode
isUnrecoverableErrortrue if GoCardless could not offer a retry — provide the payer a way to exit
ErrorDescription
TimeoutErroronReadyToFulfil was triggered but the request was not fulfilled within 10 seconds. GoCardless cancels the request and offers a retry
Authentication (with SessionTokenExpired)Session tokens are valid for 30 minutes. If the token expires mid-flow, the payer must restart

6. Prefilled customer details#

Pass prefilledCustomer in your BillingRequest factory to pre-populate the billing form. Bank details cannot be prefilled for security reasons.

const gc = GcComponents.init({
  environment: "sandbox",
  sessionToken: fetchSessionToken,
});
 
const brComponent = gc.createComponent("billing-request", {
  prefilledCustomer: {
    firstName: "Components",
    lastName: "Tester",
    email: "components-tester@example.com",
    addressLine1: "65 Goswell Road",
    addressLine2: "",
    city: "London",
    postalCode: "EC1V 7EN",
  },
});
 
brComponent.mount("#gc-billing");

Prefilled form

7. Analytics and data tracking#

GoCardless Components collects usage data to improve performance and usability. Data collection is enabled by default and can be disabled:

const config = {
  environment: "sandbox",
  sessionToken: fetchSessionToken,
  enableAnalytics: false,
};
 
GcComponents.init(config);
PurposeServiceCookiesDescription
AnalyticsGoCardless / Segmentajs_anonymous_id, analytics_session_id, analytics_session_id.last_accessTracks user events (clicks, form interactions) to improve UX. Processed via Segment

As an integrator, you are responsible for obtaining user consent for data collection, disclosing GoCardless and Segment as third parties, and updating your cookie policy accordingly.

What's next?#