Skip to main content

Freemius Overlay Checkout JavaScript API

Selling with Freemius from any website takes just a few minutes to configure. Once you have your product's plans and pricing set up within the Freemius Dashboard, simply go to the Plans section and click the Get Checkout Code button.

You'll get a ready-to-use simple JavaScript snippet that you can embed on any website.

Here's a simple example of the checkout code will look like for a plan that offers 3 multi-site prices:

<select id="licenses">
<option value="1" selected="selected">Single Site License</option>
<option value="5">5-Site License</option>
<option value="25">25-Site License</option>
</select>

<button id="purchase">Buy Button</button>

<script src="https://checkout.freemius.com/js/v1/"></script>
<script>
const checkout = new FS.Checkout({
product_id: '<productID>',
plan_id: '<planID>',
public_key: '<productPublicKey>',
image: 'https://your-plugin-site.com/logo-100x100.png',
});

document.querySelector('#purchase').addEventListener('click', function (e) {
checkout.open({
title: '<productTitle>',
licenses: document.querySelector('#licenses').value,
// You can consume the response for after purchase logic.
success: function (response) {
// alert(response.user.email);
},
});
e.preventDefault();
});
</script>

You can find more advanced multi-plan + multi-site licenses example via this Gist. For more information about the JS SDK, and to use it with NPM, please refer to our official GitHub repository.

warning

Freemius will attempt to recover the sale when a checkout is abandoned using an out-of-the-box Cart Abandonment Recovery mechanism. For this mechanism to properly work, make sure that new FS.Checkout() is called right with the page loading. Otherwise, the links in the cart recovery email campaign won't automatically open the checkout in its saved state.

Arguments

We will now go over all arguments you can pass to the FS.Checkout constructor and the open() method. We will divide it into two categories, options and callbacks.

Checkout Options

product_id
number|string
REQUIRED

Required product ID (whether it's a plugin, theme, add-on, bundle, or SaaS).

id
string
NEW

An optional ID to set the id attribute of the checkout's <body> HTML element. This argument is particularly useful if you have multiple checkout instances that need to have a slightly different design or visibility of UI components. You can assign a unique ID for each instance and customize it differently using the CSS stylesheet that you can attach through the Plans -> Customization in the Developer Dashboard.

title
string
OPTIONAL
Default: {{ productTitle }} {{ planTitle }}

An optional string to override the checkout’s title when buying a new license.

image
string
OPTIONAL
Default: The product’s title set within the Freemius dashboard.

An optional icon that loads at the checkout and will override the product’s icon uploaded to the Freemius Dashboard. Use a secure path to the image over HTTPS. While the checkout will remain PCI compliant, credit-card automatic prefill by the browser will not work.

plan_id
number
OPTIONAL
Default: The cheapest visible plan.

The ID of the plan that will load with the checkout. When selling multiple plans you can set the param when calling the open() method.

licenses
number
OPTIONAL
Default: 1

A multi-site licenses prices that will load immediately with the checkout. A developer-friendly param that can be used instead of the pricing_id. To specify unlimited licenses prices, use one of the following values: 0, null, or 'unlimited'.

disable_licenses_selector
boolean
OPTIONAL
NEW
Default: false

Set this param to true if you like to disable the licenses selector when the product is sold with multiple license activation options.

hide_licenses
boolean
OPTIONAL
NEW
Default: false

Set this param to true if you like to entirely hide the 3rd row in the header with the license selector.

pricing_id
number
OPTIONAL
Default: The plan’s single-site prices ID.

Use the licenses param instead.
An optional ID of the exact multi-site license prices that will load once the checkout opened.

billing_cycle
string
OPTIONAL
Default: 'annual'
Allowed Values: 'monthly' | 'annual' | 'lifetime'

An optional billing cycle that will be auto selected when the checkout is opened.

currency
string
OPTIONAL
Allowed Values: 'usd' | 'eur' | 'gbp' | 'auto'

auto lets the checkout automatically choose the currency based on the geolocation of the user. With the auto option, you may also want to dynamically show the prices on your pricing page according to the user’s geo. Therefore, we created checkout.freemius.com/geo.json to allow you to identify the browser’s geo and currency that the checkout will use by default.

default_currency
string
OPTIONAL
Default: usd

You could use this when the currency param is set to auto. In this case, if the auto-detected currency is not associated with any pricing, this will be the fallback currency. To set the default currency of the pricing page and checkout within the WP Admin dashboard, use the default_currency filter.

coupon
string
OPTIONAL

An optional coupon code to be automatically applied on the checkout immediately when opened.

hide_coupon
boolean
OPTIONAL
Default: false

Set this param to true if you pre-populate a coupon and like to hide the coupon code and coupon input field from the user.

maximize_discounts
boolean
OPTIONAL
DEPRECATED
Default: true
This has been deprecated in favor of bundle_discount.

Set this param to false when selling a bundle and you want the discounts to be based on the closest licenses quota and billing cycle from the child products. Unlike the default discounts calculation which is maximized by basing the discounts on the child products single-site prices.

Learn how the automatic discounts work

trial
boolean|string
OPTIONAL
Default: false
Allowed Values: true | false | 'free' | 'paid'

When set to true, it will open the checkout in a trial mode and the trial type (free vs. paid) will be based on the plan’s configuration. This will only work if you’ve activated the Free Trial functionalityin the plan configuration.

If you configured the plan to support a trial that doesn’t require a payment method, you can also open the checkout in a trial mode that requires a payment method by setting the value to 'paid'.

license_key
string
OPTIONAL

An optional param to pre-populate a license key for license renewal, license extension and more.

hide_license_key
boolean
OPTIONAL
NEW
Default: false

Set this param to true if you like to hide the option to manually enter a license key during checkout for existing license renewal.

is_payment_method_update
boolean
OPTIONAL
Default: false

An optional param to load the checkout for a payment method update. When set to true, the license_key param must be set and associated with a non-canceled subscription.

user_email
string
OPTIONAL

An optional string to prefill the buyer’s email address.

user_firstname
string
OPTIONAL

An optional string to prefill the buyer’s first name.

user_lastname
string
OPTIONAL

An optional string to prefill the buyer’s last name.

readonly_user
boolean
OPTIONAL
NEW

Set this parameter to true to make the user details (name and email) readonly. This is useful for SaaS integration where you are loading the user email and their first and last name from your own DB.

affiliate_user_id
number
OPTIONAL

An optional user ID to associate purchases generated through the checkout with their affiliate account.

language | locale
string
OPTIONAL

If given the Checkout will load in the selected language and would also show an UI for the user to switch language. The value of the language or locale parameter could be one of the followings:

  • locale: It can be a fully qualified locale code, for example: en_US, de_DE etc.
  • language: It can be just the language code, for example: en, de or fr etc. If we have more than two locales available for a language, then we have a system in place where we define the preferred language by popularity. If you are unsure about it, then please use the fully qualified locale code instead.
  • auto (recommended): The system will try to guess the language of your user by looking into the browser and then the geo-location respectively. However, this won’t select languages that are marked as AI-translated or beta for the time being. If we identify a locale that we don’t support right now, we’ll keep showing the English language. However we will still show the language selector UI.
  • auto-beta: Same as above, but will also select a language marked as beta. When a language marked as beta is selected, the UI will also show a “BETA” tag near it.
tip

Our Checkout will always display the language selector UI to the buyer. If you wish to automatically load the Checkout in the buyer’s preferred language, please use the auto value.

user_token
string
OPTIONAL

An optional token which if present, would pre-populate the checkout with user’s personal and billing data (for example, the name, email, country, vat ID etc). Learn more…

layout
string
OPTIONAL
NEW
Default: null
Allowed Values: 'vertical' | 'horizontal' | 'null'

Specify the layout of the form on a larger screen. This cannot be horizontal in cases like payment method updates or free plans. If set to null the system will automatically choose the best default for the current checkout mode.

form_position
string
OPTIONAL
NEW
Default: left
Allowed Values: 'left' | 'right'

Specifies the position of the form in horizontal layout.

fullscreen
boolean
OPTIONAL
NEW
Default: false

If set to true, the Checkout dialog will take the entire screen when opened.

show_upsells
boolean
OPTIONAL
NEW
Default: false

Whether or not showing the upsell toggles.

show_reviews
boolean
OPTIONAL
NEW
Default: false

Whether or not showing featured reviews in the checkout. By default it will be shown if the checkout page is loaded directly, without any JS snippet (iFrame) integration call.

review_id
number
OPTIONAL
NEW

When showing the review UI in the checkout, you can specify which review you want to show with its ID. By default the latest featured review will be shown.

show_refund_badge
boolean
OPTIONAL
NEW
Default: false

Whether or not showing Refund Policy UI in the checkout. By default it will be shown if the checkout page is loaded directly, without any JS snippet (iFrame) integration call.

refund_policy_position
string
OPTIONAL
NEW
Default: dynamic
Allowed Values: 'below_form' | 'below_breakdown' | 'dynamic'

Use the parameter to position the refund policy badge when showing the form in horizontal layout. By default with the 'dynamic' value, it will be positioned either below the form or the breakdown column.

annual_discount
boolean
OPTIONAL
NEW
Default: true

Determines whether the annual discount will be shown in the checkout. Learn how the automatic discounts work

show_monthly
boolean
OPTIONAL
NEW
Default: false

Switching to the monthly billing cycle is disabled when the Checkout is loaded with annual billing cycle. Use this parameter to show it.

  • Having a true value may not show the upsell toggle UI. It will show up only if the annual pricing has some discount associated with it. In case your single unit pricing doesn’t have a monthly price set, you would need to disable the multisite discount by using multisite_discount=false for the system to calculate the annual discount from currently selected license units instead of the single license unit .
  • If you are using the billing_cycle_selector UI then show_monthy will always show the monthly option regardless of any discount associated with it.

Learn how the automatic discounts work

multisite_discount
boolean|string
OPTIONAL
NEW
Default: 'auto'
Allowed Values: true | false | 'auto'

Determines whether the multi-site discount will be shown. When the value is 'auto', the discount will only be shown if the single license pricing difference does not exceed 10 times more than the current pricing.

Learn how the automatic discounts work

bundle_discount
boolean|string
OPTIONAL
NEW
Default: 'maximize'
Allowed Values: true | false | 'maximize'

Determines whether the bundle discount will be shown. The bundle discount itself depends on the compound price of its children. By default with maximize, we try to take the compound price from the lowest billing cycle and license. But with the value of true, we take it from the closest billing cycle and licenses.

Learn how the automatic discounts work

show_inline_currency_selector
boolean
OPTIONAL
NEW
Default: true

Set it to false to hide the inline currency selector from the "Today’s Total" line.

cancel_url
string
OPTIONAL
NEW

When the checkout is loaded in page you can specify a cancel URL to be used for the back button. By default if you link Freemius Checkout from your website, it will be picked up from the Referer header (if present). Using this option you can override the URL as needed.

cancel_icon
string
OPTIONAL
NEW

By default the website icon (also known as favicon) will be rendered alongside the cancel button. If you want to use any other icon image, please specify the link to the icon using this parameter.

always_show_renewals_amount
boolean
OPTIONAL
NEW
Default: false

When set to true, a small line mentioning the total renewal price per billing cycle will shown below the total. By default, it only shows up when there is a renewal discount involved.

is_bundle_collapsed
boolean
OPTIONAL
NEW
Default: true

Determines whether the products in a bundle appear as hidden by default. Is applicable only to bundles.

billing_cycle_selector
string
OPTIONAL
NEW
Default: null
Allowed Values: 'list' | 'responsive_list' | 'dropdown'

If present, it will show the billing cycle selector UI in the Checkout. The accepted values are:

  • 'responsive_list' – Displays billing cycles in a smart list that adapts to available space.
  • 'dropdown' – Shows a dropdown UI, allowing buyers to select their preferred billing cycle.
  • 'list' – Same as responsive_list but always show up vertically.

Read more about it here.

show_confirmation_dialog
boolean
OPTIONAL
NEW
Default: true

Determines whether or not to show the confirmation dialog after a successful purchase. Learn more about it here.

tip

All the parameters can be preset when creating the checkout using new FS.Checkout({ /* options */ }). If you need to set different param values based on the user's selection, you can set all the params except product_id when executing the checkout.open() method.

Callbacks

cancel
callable
OPTIONAL

A callback handler that will execute once a user closes the checkout by clicking the close icon. This handler only executes when the checkout is running in a dialog mode.

purchaseCompleted
callable(data: Object)
OPTIONAL

An after successful purchase/subscription completion callback handler. The structure of the argument is detailed here.

Notice: When the user subscribes to a recurring billing plan, this method will execute upon a successful subscription creation. It doesn’t guarantee that the subscription’s initial payment was processed successfully as well. If you’d like to leverage this method for the in-dashboard/WP-Admin checkout, you’ll need to utilize a special filter named checkout/purchaseCompleted as in this example.

success
callable(data: Object)
OPTIONAL

An optional callback handler, similar to purchaseCompleted but only triggered after the confirmation dialog is closed.

The structure of the argument is detailed here. The main difference is that this callback will only execute after the user clicks the "Got It" button that appears in the after purchase screen as a declaration that they successfully received the after purchase email. This callback is obsolete when the checkout is running in a dashboard mode.

track
callable(event: String, data: Object)
OPTIONAL
NEW

An optional callback handler for advanced tracking, which will be called on multiple checkout events such as updates in the currency, billing cycle, licenses #, etc.

User & Purchase Data in Callbacks

If you're hooking into the success or purchaseCompleted callbacks for advanced integrations, you can retrieve purchase and user information from the first argument passed to your callback. For example:

checkout.open({
success(data) {
// Get the user
console.log(data.user);
// Get the purchase
console.log(data.purchase);
},
});

The user Object

Contains details about the user who completed the purchase:

  • email: Buyer's email address
  • first: First name
  • last: Last name
  • id: Freemius user ID

The purchase Object

The purchase object differs depending on whether the transaction is a subscription or a one-off payment. Key properties include:

  • plan_id: ID of the purchased plan
  • license_id: ID of the license created or updated
  • subscription_id: ID of the subscription (only present for subscriptions)
  • billing_cycle: Subscription billing frequency (only present for subscriptions)

The full structure is documented in our repository. If you're using the @freemius/checkout package, you'll get full IDE type intellisense support.

Tracking purchases with Google Analytics and Facebook

The easiest way to track purchase conversions with external analytics and conversion tracking tools like Google Analytics is by leveraging the purchaseCompleted callback.

Here is an implementation example:

checkout.open({
// ...
purchaseCompleted: function (response) {
var isTrial = null != response.purchase.trial_ends,
isSubscription = null != response.purchase.initial_amount,
total = isTrial
? 0
: (isSubscription
? response.purchase.initial_amount
: response.purchase.gross
).toString(),
productName = 'Product Name',
storeUrl = 'https://your-site.com',
storeName = 'Store Name';

// Facebook Pixel tracking code.
if (typeof fbq !== 'undefined') {
fbq('track', 'Purchase', {
currency: response.purchase.currency.toUpperCase(),
value: total,
});
}

// The new GA4 gtag based tracking code.
if (typeof gtag !== 'undefined') {
gtag('event', 'purchase', {
transaction_id: response.purchase.id.toString(), // Transaction ID. Required.
affiliation: storeName, // Affiliation or store name.
value: total, // Grand Total.
shipping: 0, // Shipping.
tax: 0, // Tax.
currency: response.purchase.currency.toUpperCase(), // Currency.
items: [
{
item_id: response.purchase.plugin_id.toString(), // SKU/code.
item_variant: response.purchase.plan_id.toString(), // SKU/code.
item_name: productName, // Product name. Required.
item_category: 'Plugin', // Category or variation.
price: total, // Unit price.
quantity: 1, // Quantity
currency: response.purchase.currency.toUpperCase(), // Currency.
},
],
});

gtag('event', 'page_view', {
page_title: '/purchase-completed/',
page_location: storeUrl + '/purchase-completed/',
});
}
},
// ...
});
tip

If you’d like to leverage this method for the in-dashboard/WP-Admin checkout, you’ll need to utilize a special filter named checkout/purchaseCompleted as in this example.

Advanced Event Tracking

You can leverage the track callback handler to act upon different checkout actions taken by the user. Here's how you can use it including the list of the currently supported events:

checkout.open({
// ...

track: function( event, data ) {
const product = data.product;
const user = data.user;

switch (event) {
case 'load':
// Checkout loaded.
break;
case 'currency-changed':
// Currency changed.
break;
case 'licenses-inc':
// Licenses # increased.
break;
case 'licenses-dec':
// Licenses # decreased.
break;
case 'billing-cycle-updated':
// Billing cycle update.
break;
case 'email-updated':
// Email address set or updated.
break;
case 'coupon-updated':
// Coupon set or updated.
break;
case 'paypal-express-checkout':
// PayPal express checkout started.
break;
case 'review-order':
// User moved to review mode, i.e., they already filled up their payment method details and ready to confirm the purchase.
break;
case 'cooling-off-waiver-toggled':
// Cooling-off waiver toggled (only relevant for EU buyers).
break;
case 'complete':
// Purchase completed.
break;
case 'exit-intent-shown':
// Exit intent shown.
break;
case 'exit-intent-promotion-ended':
// Exit intent promotion ended.
break;
case 'exit-intent-discount-applied':
// Exit intent discount applied.
break;
case 'exit-intent-discount-canceled':
// Exit intent discount denied.
break;
}
},

// ...
});

User Token in Checkout

This feature lets you load the Freemius Checkout app where the user's name, email, VAT, country, Zip Code/Postal Code etc are already prepopulated, in a safe and secure way.

The pre-requisites are:

  1. You must know the Freemius User ID of the user going through the checkout.
  2. You must make a Freemius API call in the context of the same plugin/product for which you are loading the checkout.
  3. The token must be used immediately while loading the checkout. The lifespan of the token is 1 minutes.

High-level process

  1. When the user clicks on the purchase button, make a call to YOUR backend.
  2. Your backend will figure out the ID of the user and the ID of the product they are trying to purchase.
  3. The backend will call Freemius API to generate a token.
  4. The token would be given back to the JavaScript application which intercepted the "click".
  5. The JavaScript application will then open the Freemius checkout while passing in the generated token as user_token in the configuration.

Code example is given for both your backend (using PHP and Freemius PHP SDK) and JavaScript app.

checkout-app.js This is a sample JavaScript code that you can use to initialize the checkout on your website.

<!-- Init the Freemius Checkout JS SDK. -->
<script>
const checkout = new FS.Checkout({
plugin_id: '9889',
plan_id: '16645',
public_key: 'pk_6405fe361ba0a6e68d14fb480d98b',
image: 'https://your-plugin-site.com/logo-100x100.png'
});

// Assume the purchase button has an ID `#purchase`
const purchaseButton = document.querySelector('#purchase');

purchaseButton.addEventListener('click', async (e) => {
e.preventDefault();

// First make an API call to YOUR backend to generate the user token.
const userToken = await fetch('https://yoursite.com/generate-user-token.php', { method: 'POST' })
.then(response => response.json())
.then(data => data.token);

// Now load the Freemius Checkout with the freshly generated token.
checkout.open({
// Add the user Token as `user_token` parameter.
user_token: userToken,
// ....other configuration option
});
});
</script>

generate-user-token.php This is a sample backend code to which the JS code would make a request to get the token.

<?php

// Use the Freemius PHP SDK
define( 'FS__API_SCOPE', 'developer' );
define( 'FS__API_DEV_ID', 1234 );
define( 'FS__API_PUBLIC_KEY', 'pk_YOUR_PUBLIC_KEY' );
define( 'FS__API_SECRET_KEY', 'sk_YOUR_SECRET_KEY' );

// Init SDK.
$api = new Freemius_Api(FS__API_SCOPE, FS__API_DEV_ID, FS__API_PUBLIC_KEY, FS__API_SECRET_KEY);

// Figure out the product ID and the user ID.
$plugin_id = '...';
$user_id = '...';

// Make an API call to the token generator.
$result = $api->Api("plugins/{$plugin_id}/users/{$user_id}/tokens/checkout.json");

// Send the token back to your JS application.
echo json_encode(array(
'token' => $result['token'],
));
warning

Please generate the user_token right before opening the checkout and open the checkout as soon as the token is generated. The token has a short life-span and you must not generate it before hand.