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://code.jquery.com/jquery-1.12.4.min.js"></script> <script src="https://checkout.freemius.com/checkout.min.js"></script> <script> var handler = FS.Checkout.configure({ plugin_id: '<productID>', plan_id: '<planID>', public_key: '<productPublicKey>', image: 'https://your-plugin-site.com/logo-100x100.png' }); $('#purchase').on('click', function (e) { handler.open({ name : '<productTitle>', licenses : $('#licenses').val(), // 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.
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
FS.Checkout.configure()
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.
Argument |
---|
plugin_id number
Required product ID (whether it’s a plugin, theme, add-on, bundle, or SaaS).
|
public_key string
Require product public key.
|
id stringnew
An optional ID to set the
id attribute of the checkout’s 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. |
name stringoptional Defaults to the product’s title set within the Freemius dashboard.
An optional string to override the product’s title.
|
title stringoptional Defaults to “Great selection, {{ firstName }} !”
An optional string to override the checkout’s title when buying a new license.
|
subtitle stringoptional Defaults to “You’re one step closer to our {{ planTitle }} features”
An optional string to override the checkout’s subtitle.
|
image stringoptional Defaults to 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 numberoptional Defaults to the 1st paid 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 numberoptional Default is 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 booleanoptionalnew Default is 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 booleanoptionalnew Default is false
Set this param to
true if you like to entirely hide the 3rd row in the header with the license selector. |
pricing_id numberoptional Defaults to 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 stringoptional Default is 'annual'
An optional billing cycle that will be auto selected when the checkout is opened. Can be one of the following values:
'monthly' , 'annual' , 'lifetime' . |
hide_billing_cycles booleanoptionalnew Default is false
Set this param to
true if you like to hide the billing cycles selector when the product is sold in multiple billing frequencies. |
currency stringoptional Default is 'usd'
One of the following 3-char currency codes (ISO 4217) or
'auto' : 'usd' , 'eur' , 'gbp' .You could set the parameter to
'auto' to let the checkout automatically choose the currency based on the geolocation of the user. If you decide to choose 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 stringoptional Default is '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:function my_default_currency( $currency ) { return 'eur'; } my_fs()->add_filter( 'default_currency', 'my_default_currency' ); |
coupon stringoptional
An optional coupon code to be automatically applied on the checkout immediately when opened.
|
hide_coupon booleanoptional Default is 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 booleanoptional Default is true
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. |
trial boolean or 'free' or 'paid' optional Default is false
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 functionality in 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' . |
cancel callableoptional
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.
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 . 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)optionalnew
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.
|
license_key stringoptional
An optional param to pre-populate a license key for license renewal, license extension and more.
|
hide_license_key booleanoptionalnew Default is 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 booleanoptional Default is 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 stringoptional
An optional string to prefill the buyer’s email address.
|
user_firstname stringoptional
An optional string to prefill the buyer’s first name.
|
user_lastname stringoptional
An optional string to prefill the buyer’s last name.
|
affiliate_user_id numberoptional
An optional user ID to associate purchases generated through the checkout with their affiliate account.
|
language | locale stringoptional
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:
|
user_token stringoptional
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…
|
All the parameters can be preset when configuring the checkout using
FS.Checkout.configure()
. If you need to set different param values based on the user’s selection, you can set all the params exceptplugin_id
andpublic_key
when executing thehandler.open()
method.
To add a coupon to a URL, so your customers automatically arrive to the Freemius Checkout page with a coupon activated, all you need to do is add
?coupon=12345
to the end of the URL.12345
should be replaced with the coupon code.
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:
handler.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/', }); } // Legacy UA based GA3 tracking code. if (typeof ga !== 'undefined') { ga('send', 'event', 'plugin', 'purchase', productName); ga('require', 'ecommerce'); ga('ecommerce:addTransaction', { id: response.purchase.id.toString(), // Transaction ID. Required. affiliation: storeName, // Affiliation or store name. revenue: total, // Grand Total. shipping: '0', // Shipping. tax: '0', // Tax. }); ga('ecommerce:addItem', { id: response.purchase.id.toString(), // Transaction ID. Required. name: productName, // Product name. Required. sku: response.purchase.plan_id.toString(), // SKU/code. category: 'Plugin', // Category or variation. price: total, // Unit price. quantity: '1', // Quantity. }); ga('ecommerce:send'); ga('send', { hitType: 'pageview', page: '/purchase-completed/', location: storeUrl + '/purchase-completed/', }); } }, // ... });
This snippet was kindly contributed by James Kemp from IconicWP 🙌
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 new
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:
handler.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 new
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:
- You must know the Freemius User ID of the user going through the checkout.
- You must make a Freemius API call in the context of the same plugin/product for which you are loading the checkout.
- The token must be used immediately while loading the checkout. The lifespan of the token is 1 minutes.
High-level process
- When the user clicks on the purchase button, make a call to YOUR backend.
- Your backend will figure out the ID of the user and the ID of the product they are trying to purchase.
- The backend will call Freemius API to generate a token.
- The token would be given back to the JavaScript application which intercepted the “click”.
- The JavaScript application will then
open
the Freemius checkout while passing in the generated token asuser_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. const fsCheckout = FS.Checkout.configure({ 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. fsCheckout.open({ // Add the user Token as `user_token` parameter. user_token: userToken, // ....other configuration option }); });
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'], ));
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.