Web or Javascript
Our Checkout library provides a simple integration with your website to accept payments. You can open our checkout either as a popup modal window above your page or can simply redirect to our checkout and get control back using a callback URL.
- To see our checkout in action, visit the live demo store and perform a live transaction.
- Both the popup modal window and redirect experiences are available for you to try out.
Compatibilities and Dependencies
The Nimbbl Checkout library works with all modern browsers that support ES6 modules and JavaScript. Supported browsers include:
- Chrome: Version 61+ (supports ES6 modules)
- Firefox: Version 60+ (supports ES6 modules)
- Safari: Version 10.1+ (supports ES6 modules)
- Edge: Version 16+ (Chromium-based Edge) and Edge Legacy 15+
- Opera: Version 48+
- Mobile Browsers: iOS Safari 10.3+, Chrome Mobile 61+
If you're integrating the Nimbbl Web checkout in a mobile WebView (Android, iOS, React Native, or Flutter), you'll need to handle UPI app redirects properly. When users select a UPI app on the checkout page, the app needs to intercept the UPI app URL and open it natively. See our Mobile WebView for detailed platform-specific implementation instructions.
Import / Add the Checkout library
Import the Nimbbl Checkout JSSDK within your script tag using type="module" and the defer attribute to ensure it loads asynchronously and supports modern JavaScript modules before initializing the checkout. Refer to sample code below.
import Checkout from "https://cdn.jsdelivr.net/npm/nimbbl_sonic@latest";
Initialize Checkout
Initialize the Checkout class by providing your unique token obtained from previous step. This step should be performed on the same page where you intend to launch the checkout.
| Option Properties | Type | Mandatory? | Description |
|---|---|---|---|
| token | string | true | This would have been generated from your server during order creation using V3 create-order API. |
import Checkout from "https://cdn.jsdelivr.net/npm/nimbbl_sonic@latest";
const checkout = new Checkout({ token: "your_token_here" });
Launching the Nimbbl Checkout
Understanding Checkout Options
Read more about options object and its properties below.
Properties related to Callback Mode
Nimbbl provides you with two ways of receiving the response from SDK. This mode also determines the way in which your checkout is launched. One of the mode is, callback_handler which launches the Nimbbl Checkout within a popup modal window, alternative to this we have callback_url where the Checkout opens in the same window by redirecting users away from your page.
| Option Properties | Type | Mandatory? | Description |
|---|---|---|---|
| callback_handler | function | Required if callback_url is not passed. | Handler Function will open Nimbbl checkout in a popup modal window. On successful or failure payment, customer will get the json response with status. |
| callback_url | string | Required if callback_handler is not passed. | Checkout opens in the same window by redirecting away from your page. On successful or failure payment, customer will be redirected to the specified Callback URL, for example, a payment success page. |
Properties related to Payment Mode
Nimbbl lets you enforce a payment mode on the Checkout. This can be done by passing the payment_mode_code property. There are other related properties in to each different payment mode, you can read it in the table below. If you don't pass payment_mode_code the customer is shown the full Checkout with all available payment modes.
| Option Properties | Type | Mandatory? | Description |
|---|---|---|---|
| payment_mode_code | string | false | In case of specific payment mode, this property is mandatory. Possible values net_banking, card, upi, wallet, emi. If you don't pass payment_mode_code the customer is shown the full Checkout with all available payment modes. |
| bank_code | string | false | Only to be passed in case of net_banking. Example: hdfc. To get the full list of banks supported for you, please use this API. If it isn't passed, Checkout will open with a page for the user to choose their bank from enabled banks |
| wallet_code | string | false | Only to be passed in case of wallet. Example: jio_money. To get the full list of wallets supported for you, please use this API. If it isn't passed, Checkout will open with a page for the user to choose their wallet from enabled wallets |
| payment_flow | string | false | Only to be passed in case of upi to determine the flow. Possible value is intent. If it isn't passed, Checkout will open with page for the user to pay using a QR or choose a UPI app |
| upi_app_code | string | false | Only to be passed in case of upi and payment_flow is intent. Possible values phonepeupi, gpay. Checkout will open with the transaction initiated for the upi app passed in the upi_app_code field. If it isn't passed, Checkout will show a UPI QR or prompt user to choose a UPI app |
| emi_code | string | false | Only to be passed in case of emi. Possible values debit, credit, cardless. If it isn't passed, Checkout will show all available EMI options |
Setting the Checkout Options
Set all the relevant properties for your use case in the options object as shown below
- Callback Handler
- Callback URL
var options = {
// pass `callback_handler` if you want to open the Checkout in a popup modal.
callback_handler: function (response) {
alert(response);
},
// only if you want to enforce a specific payment mode
payment_mode_code: string,
bank_code: string,
wallet_code: string,
payment_flow: string,
upi_app_code: string,
emi_code: string,
};
var options = {
// pass `callback_url` if you want to open Checkout in the same window.
callback_url: string,
redirect: true
// only if you want to enforce a specific payment mode
payment_mode_code: string,
bank_code: string,
wallet_code: string,
payment_flow: string,
upi_app_code: string,
emi_code: string,
};
Invoking the Checkout
Finally, after setting up the options object with respective parameters, we can now invoke checkout by accessing checkout method.
checkout.open(options);
Capture Transaction Response
The final step in completing the client integration is capturing the response and sending it to your server
Checkout with Handler Function
If you used the sample code with the handler function, then:
"callback_handler": function (response){
// Process the response here and
// send the response to your server for processing
}
Checkout with Callback URL
Provided below is a detailed example that demonstrates all the code that you need to do to accept payments on your web page. Please note this example covers the popup modal flow using the callback_handler.
callback_url?response=base64_payload
You will need to decode the base64 payload. To learn how to decode the payload, you can refer here. The decoded response will need to be sent to your server.
Summary of Changes
Provided below are detailed examples that demonstrate all the code you need to accept payments on your web page. The examples cover the popup modal flow using the callback_handler.
- Integration: To integrate Nimbbl Checkout, include the provided script tag in your HTML document using
type="module"and thedeferattribute. This ensures the script asynchronously imports the Nimbbl Checkout module from the CDN and supports modern JavaScript modules. - Initialization: Create a new instance of the Nimbbl Checkout class with your authentication token.
- Configuration: Define payment options such as callback handler, payment mode code, bank code, wallet code, payment flow, UPI ID, and UPI app code.
- Opening Checkout: Call the
open()method on the Checkout instance with the configured options to open the checkout. - Capturing Response: To finalize client integration, capture transaction response and forward it to your server. If utilizing a handler function, process the response within it. For callback URL usage, decode the base64 payload and transmit the decoded response to your server for processing.
- Without Tracking Integration
- With Tracking Integration (Recommended)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nimbbl Checkout Integration</title>
<link rel="stylesheet" href="style.css" />
<!-- DNS prefetch for external domains -->
<link rel="dns-prefetch" href="//cdn.jsdelivr.net" />
<!-- Preconnect to external domains for faster connection -->
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
</head>
<body>
<div>
<button id="checkoutBtn" class="checkout-button">
Proceed to Checkout
</button>
</div>
<!-- Load main checkout logic with defer -->
<script defer>
// Initialize checkout function with improved error handling
async function initializeCheckout(token) {
try {
// Load Nimbbl Sonic module with timeout
const checkoutPromise = import(
"https://cdn.jsdelivr.net/npm/nimbbl_sonic@latest"
);
// Add timeout for module loading
const timeoutPromise = new Promise((_, reject) => {
setTimeout(
() => reject(new Error("Module loading timeout")),
10000
);
});
const checkoutModule = await Promise.race([
checkoutPromise,
timeoutPromise,
]);
const Checkout = checkoutModule.default;
const checkout = new Checkout({ token: token });
const options = {
callback_handler: function (response) {
console.log("Payment response:", response);
},
};
checkout.open(options);
} catch (error) {
console.error("Failed to load checkout:", error);
}
}
// Main checkout flow
async function handleCheckout() {
try {
// this token should be generated by the merchant S2S
const token =
"YOUR_TOKEN_HERE";
if (!token) {
throw new Error("No token received from order creation");
}
// Step 2: Initialize and open checkout
await initializeCheckout(token);
} catch (error) {
console.error("Checkout failed:", error);
}
}
// Wait for DOM to be ready before adding event listeners
document.addEventListener("DOMContentLoaded", function () {
const checkoutBtn = document.getElementById("checkoutBtn");
if (checkoutBtn) {
checkoutBtn.addEventListener("click", handleCheckout);
}
});
</script>
</body>
</html>
Tracking Implementation
To help with error investigation and debugging, merchants are required to implement tracking for the checkout flow. This helps Nimbbl investigate any issues during token generation and checkout launch process.
Required Tracking File
Create a tracking.js file in your project with the following implementation. Copy the code below and save it as tracking.js in your project.
📥 Copy the tracking.js code below and save it as tracking.js
This file includes:
- Complete tracking implementation
- Helper functions for all required events
- Proper error handling
- JSDoc documentation
- Customizable merchant IDs and endpoint
Steps to use:
- Copy the entire code block below
- Create a new file named
tracking.jsin your project - Paste the code and customize with your merchant details
- Include the file in your HTML as shown in the examples
/**
* Nimbbl Checkout Tracking Implementation
*
* This file provides tracking functionality for Nimbbl Checkout integration.
* Merchants should customize this file with their specific merchant ID and any additional tracking requirements.
*
* Required Events to Track:
* - page_loaded: When the page loads
* - nimbbl_script_loaded: When Nimbbl script loads successfully
* - nimbbl_script_failed: When Nimbbl script fails to load
* - payment_completed: When payment is completed
* - checkout_failed: When checkout process fails
* - checkout_launched_successfully: When checkout is launched successfully
* - nimbbl_sonic_loaded: When Nimbbl Sonic library loads successfully
*/
// Replace with your actual merchant ID and submerchant ID
const merchantId = "your_merchant_id_here";
const submerchantId = "your_submerchant_id_here";
// Tracking endpoint - replace with your tenant ID
var samunnayaEndpoint =
"https://eventlogpipe.nimbbl.tech/v1/log?tenantId=6e7e900c-9ce6-4271-b1ec-08875a9129d1";
/**
* Tracking function to log events
* @param {string} name - Event name
* @param {object} data - Event data
* @param {string} orderId - Order ID (optional)
*/
const tracking = (name, data, orderId) => {
const now = new Date();
const headers = { "Content-Type": "application/json" };
const payload = {
name: name,
data:
typeof data === "object"
? {
...data,
event_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
event_time_local: now.toString(),
event_time_utc: now.toUTCString(),
}
: null,
orderId: orderId || null,
merchantId: merchantId,
submerchantId: submerchantId,
eventTimestamp: now.toISOString(),
host: window?.location.href || null,
};
fetch(samunnayaEndpoint, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => {
if (!response.ok) {
console.log("Logging Failed:", response.status);
}
})
.catch((error) => {
console.error("Tracking error:", error);
});
};
/**
* Common tracking data structure used across all events
* @param {object} result - Order creation result (optional)
* @returns {object} Common tracking data
*/
const getCommonTrackingData = (result = null) => {
return {
application_name: "Checkout",
library_name: "client_page_js_sdk",
merchant_shopfront_domain: window?.location.href,
token_expiry_date: result?.token_expiration
? new Date(result.token_expiration).toUTCString()
: null,
product_name: "Payments",
};
};
/**
* Track script load event
*/
const trackingScriptLoaded = () => {
tracking(
"tracking_script_loaded",
{
application_name: "Checkout",
library_name: "client_page_js_sdk",
library_version: "",
app_version: "",
merchant_shopfront_domain: window?.location.href,
product_name: "Payments",
},
null
);
};
/**
* Track script loading success
* @param {string} orderId - Order ID (optional)
*/
const trackScriptLoaded = (orderId = null) => {
tracking(
"nimbbl_script_loaded",
{
...getCommonTrackingData(),
message: "success",
},
orderId
);
};
/**
* Track script loading failure
* @param {string} errorMessage - Error message
* @param {string} orderId - Order ID (optional)
*/
const trackScriptFailed = (errorMessage, orderId = null) => {
tracking(
"nimbbl_script_failed",
{
...getCommonTrackingData(),
message: errorMessage,
},
orderId
);
};
/**
* Track payment completion
* @param {object} response - Payment response
*/
const trackPaymentCompleted = (response) => {
tracking(
"payment_completed",
{
...getCommonTrackingData(),
callback_handler_response: response,
},
response?.order_id
);
};
/**
* Track checkout failure
* @param {string} errorMessage - Error message
* @param {string} orderId - Order ID (optional)
*/
const trackCheckoutFailed = (errorMessage, orderId = null) => {
tracking(
"checkout_failed",
{
...getCommonTrackingData(),
message: errorMessage,
},
orderId
);
};
/**
* Track checkout launched successfully
* @param {string} orderId - Order ID (optional)
*/
const trackCheckoutLaunchedSuccessfully = (options, orderId = null) => {
tracking(
"checkout_launched_successfully",
{
...getCommonTrackingData(),
message: "success",
checkout_options: options,
},
orderId
);
};
/**
* Track nimbbl sonic library loaded successfully
* @param {object} checkoutModule - The loaded checkout module
* @param {string} orderId - Order ID (optional)
*/
const trackNimbblSonicLoaded = (checkoutModule, orderId = null) => {
tracking(
"nimbbl_sonic_loaded",
{
...getCommonTrackingData(),
message: "success",
module_available: !!checkoutModule,
module_type: typeof checkoutModule,
has_default_export: !!checkoutModule?.default,
},
orderId
);
};
// Log page load only after everything is fully loaded
window.addEventListener("load", function () {
trackingScriptLoaded();
});
// Export functions for use in other scripts (if using modules)
if (typeof module !== "undefined" && module.exports) {
module.exports = {
tracking,
getCommonTrackingData,
trackingScriptLoaded,
trackScriptLoaded,
trackScriptFailed,
trackPaymentCompleted,
trackCheckoutFailed,
trackCheckoutLaunchedSuccessfully,
trackNimbblSonicLoaded,
};
}
Include Tracking Script
Add the tracking script to your HTML:
<!-- Preload critical resources -->
<link rel="preload" href="tracking.js" as="script" />
<!-- DNS prefetch for external domains -->
<link rel="dns-prefetch" href="//eventlogpipe.nimbbl.tech" />
<link rel="dns-prefetch" href="//cdn.jsdelivr.net" />
<!-- Preconnect to external domains for faster connection -->
<link rel="preconnect" href="https://eventlogpipe.nimbbl.tech" crossorigin />
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<!-- Load tracking script with defer for better performance -->
<script src="tracking.js" defer></script>
Tracking Events in Checkout Flow
The following events must be tracked throughout the checkout process. All tracking calls should use the commonTrackingData structure and spread it with any additional data.
The tracking.js file includes helper functions for each event type. You can use these instead of manual tracking calls:
trackingScriptLoaded()- Track when tracking script loads (automatically called)trackScriptLoaded(orderId)- Track successful Nimbbl script loadingtrackScriptFailed(errorMessage, orderId)- Track script loading failuretrackPaymentCompleted(response)- Track payment completiontrackCheckoutFailed(errorMessage, orderId)- Track checkout failuretrackCheckoutLaunchedSuccessfully(options, orderId)- Track successful checkout launchtrackNimbblSonicLoaded(checkoutModule, orderId)- Track Nimbbl Sonic library loading
1. Tracking Script Loaded (Automatic)
// This is automatically called when the page loads
// No manual call needed - handled by tracking.js
trackingScriptLoaded();
2. Script Loading
// After successful Nimbbl script loading
trackScriptLoaded(orderId);
// If script loading fails
trackScriptFailed(error.message, orderId);
3. Nimbbl Sonic Library Loading
// After successfully loading the Nimbbl Sonic module
const checkoutModule = await import(
"https://cdn.jsdelivr.net/npm/nimbbl_sonic@latest"
);
trackNimbblSonicLoaded(checkoutModule, orderId);
4. Checkout Launch
// After successfully opening the checkout
const options = {
callback_handler: function (response) {
// Handle payment response
},
};
checkout.open(options);
trackCheckoutLaunchedSuccessfully(options, orderId);
5. Payment Completion
// In callback handler
callback_handler: function (response) {
console.log("Payment response:", response);
trackPaymentCompleted(response);
// Handle payment completion
}
6. Checkout Failure
// If checkout fails at any point
trackCheckoutFailed(error.message, orderId);
7. Using Common Tracking Data
// You can also use the common tracking data function directly
const commonData = getCommonTrackingData();
tracking(
"custom_event",
{
...commonData,
custom_field: "custom_value",
},
orderId
);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nimbbl Checkout Integration</title>
<link rel="stylesheet" href="style.css" />
<!-- Preload critical resources -->
<link rel="preload" href="nimbbl-tracking.js" as="script" />
<link rel="preload" href="scripts.js" as="script" />
<!-- DNS prefetch for external domains -->
<link rel="dns-prefetch" href="//eventlogpipe.nimbbl.tech" />
<link rel="dns-prefetch" href="//cdn.jsdelivr.net" />
<!-- Preconnect to external domains for faster connection -->
<link
rel="preconnect"
href="https://eventlogpipe.nimbbl.tech"
crossorigin
/>
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<!-- Load tracking script with defer for better performance -->
<script src="nimbbl-tracking.js" defer></script>
<script src="scripts.js" defer></script>
</head>
<body>
<div>
<button id="checkoutBtn" class="checkout-button">
Proceed to Checkout
</button>
</div>
<!-- Load main checkout logic with defer -->
<script defer>
// Initialize checkout function with improved error handling
async function initializeCheckout(token) {
try {
// Load Nimbbl Sonic module with timeout
const checkoutPromise = import(
"https://cdn.jsdelivr.net/npm/nimbbl_sonic@latest"
);
// Add timeout for module loading
const timeoutPromise = new Promise((_, reject) => {
setTimeout(
() => reject(new Error("Module loading timeout")),
10000
);
});
const checkoutModule = await Promise.race([
checkoutPromise,
timeoutPromise,
]);
const Checkout = checkoutModule.default;
// Track successful library loading
trackNimbblSonicLoaded(checkoutModule, "orderID");
const checkout = new Checkout({ token: token });
const options = {
callback_handler: function (response) {
trackPaymentCompleted(response);
},
};
checkout.open(options);
// Log checkout loaded event
trackCheckoutLaunchedSuccessfully(options, "orderID");
} catch (error) {
// Log checkout failed event
trackCheckoutFailed(error.message, "orderID");
}
}
// Main checkout flow
async function handleCheckout() {
try {
// this token should be generated by the merchant S2S
const token =
"YOUR_TOKEN_HERE";
if (!token) {
throw new Error("No token received from order creation");
}
// Step 2: Initialize and open checkout
await initializeCheckout(token);
} catch (error) {
// Log checkout failed event
trackCheckoutFailed(error.message, "orderID");
}
}
// Wait for DOM to be ready before adding event listeners
document.addEventListener("DOMContentLoaded", function () {
const checkoutBtn = document.getElementById("checkoutBtn");
if (checkoutBtn) {
checkoutBtn.addEventListener("click", handleCheckout);
}
});
</script>
</body>
</html>
- Share the response parameters received to your server
- This will need to be validated on your server before you decide to provide goods or services
- More details available on processing the response in Completing the Integration