Skip to main content

Add Bike Leasing Widget

IMPORTANT – Germany only

The Leasing Widget is intended exclusively for use in the German market.
All leasing calculations are based on the German tax and social security system and are not valid for other countries or tax regimes.

This documentation describes the complete integration of the leasing widget into your shop. It is structurally based on the Smartfit docs for product sizing and extends them with all required variables/attributes for the leasing widget as well as platform-independent examples.

1) Requirements & Setup

1.1 Include the Loader Script

Include the loader script once (e.g., in the <head>):

<script
type="module"
src="https://widget3.smartfit.online/?apiKey={{ ADD YOUR API KEY }}"
async
></script>

The loader is required because it initializes the Smartfit custom elements.

ℹ️ INFO
This is the same loader that is used for the Smartfit Sizing Widget – if it is already included, you don’t need to add an additional script. You will receive your API key from your Smartfit account.

1.2 Load Only on Relevant Pages

Only load the widget on product detail pages where leasing is appropriate (e.g., bikes/e-bikes). Use simple route/template or category checks to ensure the script is not loaded on listing, cart, or checkout pages.

2) Custom Element & Attributes

The leasing widget is embedded using the custom element <sf-product-leasing>. The following attributes are relevant:

  • name (String, required) – Product name as displayed on the PDP.
  • sale-price (Number, required) – Current sales price as a decimal number (e.g., 3499.00), without currency symbol.
  • retail-price (Number, required) – MSRP/Compare-at price as a decimal number.

Optional attributes:

  • dealer-leasing-price (Number, optional) – Dealer price for leasing calculation as a decimal.
  • style-name (String, optional): If a custom style was set up for you, reference it here via the style name.
  • workflow (String, optional) – Backend workflow/profile (e.g., leasing-rate).

Formatting Requirements:

  • Decimal point . as separator, no thousand separators/spaces, no currency symbols.
  • Values can be numbers or numeric strings (e.g., "3499.00").

Minimal Example:

<sf-product-leasing
name="Mountainbike Pro 29"
sale-price="3499.00"
retail-price="3799.00"
dealer-leasing-price="3499.00"
workflow="production"
>
<template slot="approximation"></template>
<template slot="calculation"></template>
</sf-product-leasing>

3) States & Templating

The element has two states, defined via <template> slots:

  • approximation – User has not yet entered data (default assumptions are used).
  • calculation – User has already entered data (e.g., gross income/tax class).

Structure:

<sf-product-leasing>
<template slot="approximation"></template>
<template slot="calculation"></template>
</sf-product-leasing>

3.1 Placeholders (Slots) for Dynamic Values

Available Slot Names:

  • rate – Monthly net leasing rate, with currency (e.g., “€83”)
  • savings – Savings compared to buying, with currency (e.g., “€123.45”)
  • savings-percent – Percentage savings (e.g., “14.3%”)
  • price – Current purchase price, with currency (e.g., “€4,500”)
  • leasing-price – Total leasing price incl. takeover, with currency (e.g., “€3,000”)
  • duration – Leasing duration in months (e.g., “36”)

Example Use:

<slot name="rate"></slot>

4) CTA Detection & Interaction

  • The widget automatically detects exactly one CTA element (<button> or <a>) per template.
  • If multiple potential CTAs exist or a different element should be clickable, mark the desired element with data-sf-button.
  • For buttons, consider using type="button" to prevent unwanted form submissions.
  • For non-button elements (e.g., <div>), also add data-sf-button.

5) Examples (Platform-Independent)

All examples use the attributes name, sale-price, retail-price, dealer-leasing-price, optionally workflow, and include rate for monthly amounts.

5.1 Entire Text Clickable

<sf-product-leasing
name="Mountainbike Pro 29"
sale-price="3499.00"
retail-price="3799.00"
dealer-leasing-price="3499.00"
>
<template slot="approximation">
<div
class="price price--large"
data-sf-button
role="button"
tabindex="0"
aria-label="Calculate leasing benefit"
style="flex-flow: column nowrap; cursor: pointer"
>
<div>or via leasing from <slot name="rate"></slot> per month*</div>
<div style="font-weight: bold; text-decoration: underline">
Check now without obligation
</div>
</div>
</template>
<template slot="calculation">
<!-- Same structure as above -->
</template>
</sf-product-leasing>

5.2 Only CTA Text Clickable

<sf-product-leasing
name="City E‑Bike 500"
sale-price="2999.00"
retail-price="3299.00"
dealer-leasing-price="2999.00"
>
<template slot="approximation">
<span class="price price--large">
or via leasing from <slot name="rate"></slot> per month*
<button
type="button"
style="all: unset; font-weight: bold; text-decoration: underline; cursor: pointer"
>
Check now
</button>
</span>
</template>
<template slot="calculation">
<!-- Same structure -->
</template>
</sf-product-leasing>

5.3 Only Button Clickable

<sf-product-leasing
name="Gravel 1x11"
sale-price="2599.00"
retail-price="2799.00"
dealer-leasing-price="2599.00"
>
<template slot="approximation">
<span class="price price--large">
or via leasing from <slot name="rate"></slot> per month*
<button type="button" class="button button--secondary">Check now</button>
</span>
</template>
<template slot="calculation">
<!-- Same structure -->
</template>
</sf-product-leasing>

5.4 Full-Width Button

<sf-product-leasing
name="Trail Hardtail"
sale-price="1899.00"
retail-price="2099.00"
dealer-leasing-price="1899.00"
>
<template slot="approximation">
<button
type="button"
class="button button--full-width button--secondary"
style="flex-flow: column nowrap; padding: 0.75em; text-align: center; text-wrap: balance; box-sizing: border-box"
aria-label="Calculate leasing benefit"
>
<div>or via leasing from <slot name="rate"></slot> per month*</div>
<div>Check now without obligation</div>
</button>
</template>
<template slot="calculation">
<!-- Same structure -->
</template>
</sf-product-leasing>
<sf-product-leasing
name="Urban Commuter"
sale-price="2199.00"
retail-price="2399.00"
dealer-leasing-price="2199.00"
>
<template slot="approximation">
<span class="price price--large">
or via leasing from <slot name="rate"></slot> per month*
<button
data-sf-button
type="button"
style="all: unset; font-weight: bold; text-decoration: underline; cursor: pointer"
>
Check now
</button>
<a href="/leasing-info">Our leasing terms</a>
</span>
</template>
<template slot="calculation">
<!-- Same structure -->
</template>
</sf-product-leasing>

6) Variant Changes (Short Version)

For variant switching, update values directly on the widget:

<script>
const widget = document.querySelector("#leasing-widget");
widget?.setAttribute("sale-price", newSalePrice);
widget?.setAttribute("retail-price", newRetailPrice);
widget?.setAttribute("dealer-leasing-price", newDealerPrice);
widget?.setAttribute("name", newTitle);
</script>
warning

Ensure the script runs after the browser has created the HTML element.

Option 1 - Place the script tag after the widget HTML element.

Option 2 - Attach the function to the window load event.

7) Styling

  • You can use existing button/typography classes from your frontend.
  • Use type="button" for safety to avoid unintended submissions.

8) Go‑Live Checklist

  • Loader script correctly included (with API key).
  • Widget only loaded on relevant PDPs (route/template/category checks).
  • Attribute values present and properly formatted (name, sale-price, retail-price; optional: dealer-leasing-price, workflow).
  • Exactly one CTA or data-sf-button set per template.
  • Variant switch reliably triggers updateLeasingWidget(...).

9) Differences from Product Sizing Integration (Short Overview)

  • Element: Leasing uses <sf-product-leasing> with template slots; sizing uses <sf-product-sizing> (options incl. fallback).
  • Attributes: Sizing requires e.g., global-id, variant-id, image, price, product-type; leasing focuses on price/leasing attributes (sale-price, retail-price, dealer-leasing-price) plus name & optionally workflow.
  • Content: Leasing renders values via slots (rate, savings, etc.); sizing primarily configures the button/widget.
  • CTA: Leasing auto-detects CTA or uses data-sf-button; sizing defines button as a child element (with fallback option).