Callbacks

Run custom JavaScript after key FastSpring events like add to cart or checkout complete

Using callbacks in Store Builder

Use callbacks to run JavaScript functions after specific FastSpring events. You can define a named function that runs when buyers add a product, complete a purchase, apply a promo code, or trigger a validation error. This lets you control post-event behavior in your store checkout.

Why use callbacks?

  • Real-time updates: React to cart changes, purchase events, or validation errors
  • Custom logic: Add behavior when FastSpring actions complete
  • Integrations: Send data to analytics tools, CRMs, or your own backend

What this guide covers

This guide explains how to:

  • Use data callbacks to access FastSpring session data and error messages
  • Use popup callbacks to track checkout completion or webhook events
  • Use markup callbacks to interact with FastSpring-rendered elements
  • Use request callbacks to react to actions like "add to cart"
  • Add advanced behavior with debug mode, URL decoration, and continuous mode

Requirements

Before using callbacks, make sure you:

  • Include the FastSpring Store Builder script
    This script must be added to your page before any callback functions are triggered.

    Click to view script
    <script 
        id="fsc-api"
        src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
        type="text/javascript"
        data-storefront="your-storefront-URL">
    </script>
    

    Replace your-storefront-URL with the full path to a checkout in your store.

    Attribute Description
    id Identifies the script block (must be set to fsc-api)
    src Specifies the version of the Store Builder
    type Declares the script as JavaScript
    data-storefront The storefront URL this script will connect to
  • Define your callback functions in the global scope
    These functions must be declared before the script triggers the related event.


Quick start

This section walks you through enabling callbacks in your FastSpring integration:

  1. Add the Store Builder script

    Add the script to your page before any FastSpring-specific logic:

    <script 
      id="fsc-api"
      src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
      type="text/javascript"
      data-storefront="your-storefront-URL">
    </script>
    
  2. Define a callback function

    Declare a JavaScript function and assign it to the callback name used in your markup:

    function dataCallback(data) {
      try {
        console.log("FastSpring event triggered:", data);
      } catch (error) {
        console.error("Callback error:", error);
      }
    }
    

    You can define as many callbacks as you need. Just make sure the function name matches what’s used in your data-* attribute.


Callbacks summary

The table below provides an overview of available callbacks, what they do, and the type of data they return.

Callback Description Returned data Example
data-after-markup-callback Fires after FastSpring markup is fully rendered on the page. Use this callback to interact with or modify elements that depend on FastSpring data. None View Code
data-before-markup-callback Fires just before FastSpring markup is injected into the DOM. You can use this to reset, clear, or prepare elements before rendering happens. None View Code
data-after-requests-callback Fires after a FastSpring request completes, such as adding a product to the cart. Use this to update your UI or respond to completed actions. None View Code
data-before-requests-callback Fires just before a FastSpring request is sent. This is useful for validating inputs, preparing state, or showing a loading indicator. None View Code
data-continuous Enables persistent Store Builder behavior across page refreshes or route changes. This helps maintain session state in single-page applications. None View Code
data-data-callback Fires when FastSpring session data becomes available or is updated. Use this callback to access cart contents, pricing, and other session information. (data)
data: The full session object returned by FastSpring.
View Code
data-decorate-callback Allows you to customize the FastSpring checkout URL before the buyer is redirected. Common use cases include appending UTM parameters or analytics data. (url)
url: The original FastSpring checkout URL. Return a modified version if needed.
View Code
data-debug Enables console debugging output when set to true. This is helpful for troubleshooting during development. None View Code
data-error-callback Fires when a backend error occurs, such as trying to add a product that doesn't exist. Use this callback to handle errors and display custom messages. (errorCode, errorMessage)
errorCode: The identifier for the error.
errorMessage: A description of what went wrong.
View Code
data-popup-closed Fires after the FastSpring popup window is closed, either after purchase or cancelation. This is useful for confirming what happened in the popup. (data)
data: An object that includes order ID and purchase reference.
View Code
data-validation-callback Fires when input validation fails (e.g., email, country, tax ID). Use this to identify specific fields that need to be corrected. (validationErrors[])
validationErrors: An array of error objects including a code and display message for each issue.
View Code
data-popup-webhook-received Fires when FastSpring receives a webhook event during popup checkout. This gives you access to real-time event data for the order. (data)
data: The webhook payload object with order and customer details.
View Code

Detailed callback examples

Below are detailed examples for each callback. Click each section to see the code snippet, what it does, and how to use it.

data-after-markup-callback

HTML markup + FastSpring script setup:

<!-- Optional: Element used to show callback status -->
<div id="callback-status-message">Loading...</div>

<!-- Load the Store Builder with a named callback function -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-after-markup-callback="dataAfterMarkupCallback">
</script>

JavaScript callback function:

function dataAfterMarkupCallback() {
  console.log("FastSpring markup has finished rendering.");

  // Optional: update a DOM element for visible feedback
  const status = document.getElementById("callback-status-message");
  if (status) {
    status.textContent = "Markup rendered.";
  }
}

What it does:
This callback runs once FastSpring markup has been injected into the page. It’s helpful for running logic that interacts with or modifies elements that depend on FastSpring rendering.

What to update:

  • Replace your-storefront-URL with the full path to a checkout in your store.
  • Rename dataAfterMarkupCallback if you already have a function defined elsewhere or want a different name.
data-before-markup-callback

HTML markup + FastSpring script setup:

<!-- Optional: Element used to show callback status -->
<div id="callback-status-message">Loading...</div>

<!-- Load the Store Builder with a named callback function -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-before-markup-callback="dataBeforeMarkupCallback">
</script>

JavaScript callback function:

function dataBeforeMarkupCallback() {
  console.log("FastSpring markup has finished rendering.");

  // Optional: update a DOM element for visible feedback
  const status = document.getElementById("callback-status-message");
  if (status) {
    status.textContent = "Markup injection starting...";
  }
}

What it does:
This callback runs just before FastSpring markup is injected into the page. It’s useful for clearing or preparing elements before they are updated.

What to update:

  • Replace your-storefront-URL with the full path to a checkout in your store.
  • Rename dataBeforeMarkupCallback if you already have a function defined elsewhere or want a different name.
data-after-requests-callback

HTML markup + FastSpring script setup:

<!-- Optional: Element used to show callback status -->
<div id="callback-status-message">Waiting for request...</div>

<!-- Button included to demonstrate how the callback gets triggered -->
<button data-fsc-item-path-value="your-product-path" data-fsc-action="Add">
  Add to Cart
</button>

<!-- Load the Store Builder with a named callback function -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-after-requests-callback="dataAfterRequestsCallback">
</script>

JavaScript callback function:

function dataAfterRequestsCallback() {
  console.log("FastSpring markup has finished rendering.");

  // Optional: update a DOM element for visible feedback
  const status = document.getElementById("callback-status-message");
  if (status) {
    status.textContent = "FastSpring request completed.";
  }
}

What it does:
This callback runs after a FastSpring request completes, such as when a buyer adds a product to the cart. It’s useful for logging activity or updating the UI based on user interactions.

What to update:

  • Replace your-product-path with the path of a product from your store (e.g., phot-io-main-app).
  • Replace your-storefront-URL with the full path to a checkout in your store.
  • Rename dataAfterRequestsCallback if you already have a function defined elsewhere or want a different name.
data-before-requests-callback

HTML markup + FastSpring script setup:

<!-- Optional: Element used to show callback status -->
<div id="callback-status-message">Waiting to send request...</div>

<!-- Button included to demonstrate how the callback gets triggered -->
<button data-fsc-item-path-value="your-product-path" data-fsc-action="Add">
  Add to Cart
</button>

<!-- Load the Store Builder with a named callback function -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-before-requests-callback="dataBeforeRequestsCallback">
</script>

JavaScript callback function:

function dataBeforeRequestsCallback() {
  console.log("FastSpring markup has finished rendering.");

  // Optional: update a DOM element for visible feedback
  const status = document.getElementById("callback-status-message");
  if (status) {
    status.textContent = "Preparing FastSpring request...";
  }
}

What it does:
This callback runs before a FastSpring request is sent, such as when a buyer adds a product to the cart. It’s useful for preparing the UI or running logic before the request is made.

What to update:

  • Replace your-product-path with the path of a product from your store (e.g., phot-io-main-app).
  • Replace your-storefront-URL with the full path to a checkout in your store.
  • Rename dataBeforeRequestsCallback if you already have a function defined elsewhere or want a different name.
data-continuous

HTML markup + FastSpring script setup:

<!-- Buttons demonstrate that cart contents persist after refresh -->
<button data-fsc-item-path-value="your-product-path" data-fsc-action="Add, ViewCart">
  Add to Cart
</button>
<button data-fsc-action="ViewCart">
  View Cart
</button>

<!-- Visual indicator that the product is in the cart -->
In cart:
<span data-fsc-item-path="your-product-path" data-fsc-item-selected></span>

<!-- Load the Store Builder with session persistence enabled -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-continuous="true">
</script>

What it does:
This setup allows FastSpring to persist the shopping cart between page refreshes. If a product is added, it will still appear in the cart after a reload. The data-fsc-item-selected directive shows a visual indicator when the product is in the cart.

What to update:

  • Replace your-product-path with the path of a product from your store (e.g., phot-io-main-app).
  • Replace your-storefront-URL with the full path to a checkout in your store.
data-data-callback

HTML markup + FastSpring script setup:

<!-- Optional: Element used to display the returned data -->
<div id="log">No session data yet.</div>

<!-- Button included to demonstrate how the callback gets triggered -->
<button onclick="fastspring.builder.add('your-product-path')">
  Add to Cart
</button>

<!-- Load the Store Builder with a named callback function -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-data-callback="dataCallback"
  data-continuous="true">
</script>

JavaScript callback function:

function dataCallback(data) {
  console.log("FastSpring markup has finished rendering.");

  // Optional: update a DOM element to show the returned session data
  const output = document.getElementById("log");
  if (output) {
    output.innerHTML = "<pre>" + JSON.stringify(data, null, 4) + "</pre>";
  }
}

Tip: You can use this to log cart contents, buyer email, and product selections for analytics or debugging.

What it does:
This callback runs whenever FastSpring session data is updated. It’s useful for debugging or extracting real-time session data for custom logic.

What to update:

  • Replace your-product-path with the path of a product from your store (e.g., phot-io-main-app).
  • Replace your-storefront-URL with the full path to a checkout in your store.
  • Rename dataCallback if you already have a function defined elsewhere or want a different name.
data-decorate-callback

HTML markup + FastSpring script setup:

<!-- Button to trigger checkout and decorate the URL -->
<button data-fsc-item-path-value="your-product-path" data-fsc-action="Add, Checkout">
  Add to Cart
</button>

<!-- Load the Store Builder with a decorate callback -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-decorate-callback="decorateURL">
</script>

<!-- Optional: Google Analytics setup -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXX-X"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag() { dataLayer.push(arguments); }
  gtag('js', new Date());
  gtag('config', 'UA-XXXXXXX-X');
</script>

JavaScript callback function:

function decorateURL(url) {
  var linkerParam = null;

  // Attempt to get the Google Analytics linker param
  ga(function() {
    var trackers = ga.getAll();
    if (trackers.length > 0) {
      linkerParam = trackers[0].get('linkerParam');
    }
  });

  // Append the param to the checkout URL if available
  return linkerParam ? url + '?' + linkerParam : url;
}

What it does:
This callback lets you customize the FastSpring checkout URL before redirecting the buyer. It’s commonly used to append tracking parameters, such as Google Analytics linker data for cross-domain attribution.

What to update:

  • Replace your-product-path with the path of a product from your store (e.g., phot-io-main-app).
  • Replace your-storefront-URL with the full path to a checkout in your store.
  • Replace UA-XXXXXXX-X with your Google Analytics tracking ID if using GA.
data-debug

HTML markup + FastSpring script setup:

<!-- Load the Store Builder with debug mode enabled -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-debug="true">
</script>

What it does:
Enables debug logging in the browser console. This is useful during development to see the raw data being passed through the Store Builder.

What to update:

  • Replace your-storefront-URL with the full path to a checkout in your store.
data-error-callback

HTML markup + FastSpring script setup:

<!-- Button included to trigger an error using an invalid product -->
<button onclick="fastspring.builder.add('bogus')">
  Add invalid product
</button>

<!-- Load the Store Builder with an error callback -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-error-callback="dataErrorCallback"
  data-continuous="true">
</script>

JavaScript callback function:

function dataErrorCallback(code, string) {
  console.log("Error:", code, string);
}

What it does:
This callback runs when a FastSpring request results in an error (e.g., using an invalid product path). It’s useful for logging or displaying error messages.

What to update:

  • Replace your-storefront-URL with the full path to a checkout in your store.
  • Rename dataErrorCallback if you already have a function defined elsewhere.
data-popup-closed

HTML markup + FastSpring script setup:

<!-- Optional: Element used to show the returned data -->
<div id="callback-status-message">Waiting for popup close...</div>

<!-- Button to trigger the checkout popup -->
<button onclick="fastspring.builder.checkout()">Checkout</button>

<!-- Load the Store Builder with the popup closed callback -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-popup-closed="dataPopupClosed"
  data-continuous="true">
</script>

<!-- Preload cart contents for demo purposes -->
<script>
  fastspring.builder.reset();
  fastspring.builder.add("your-product-path");
</script>

JavaScript callback function:

function dataPopupClosed(data) {
  const status = document.getElementById("callback-status-message");
  if (status) {
    status.innerHTML = "<pre>" + JSON.stringify(data, null, 4) + "</pre>";
  }
}

What it does:
This callback runs when a buyer closes the FastSpring popup window (after checkout or cancel). It’s useful for tracking or displaying the result of the checkout interaction.

What to update:

  • Replace your-product-path with a product from your store.
  • Replace your-storefront-URL with your full storefront checkout URL.
  • Rename dataPopupClosed if you’re using a different function.
data-validation-callback

HTML markup + FastSpring script setup:

<!-- Button to simulate validation errors -->
<button onclick="recognize()">Trigger Validation Errors</button>

<!-- Load the Store Builder with a validation callback -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-validation-callback="dataValidationCallback">
</script>

JavaScript callback function:

function dataValidationCallback(error) {
  for (let i = 0; i < error.length; i++) {
    if (error[i].error) {
      console.log("error code:", error[i].error.code);
      console.log("error display:", error[i].error.display);
    }
  }
}

function recognize() {
  fastspring.builder.recognize({ email: "bruce@", postalCode: "867-5309" });
  fastspring.builder.country("not a valid country");
  fastspring.builder.taxId("not a valid tax id");
  fastspring.builder.language("not a valid language");
  fastspring.builder.promo("not a valid promo code");
}

What it does:
This callback is triggered when invalid data is passed to the SBL (e.g., during recognize() or localization updates). It helps you identify specific field-level validation errors.

What to update:

  • Replace your-storefront-URL with your FastSpring storefront URL.
  • Rename dataValidationCallback or recognize() if needed for your implementation.
data-popup-webhook-received

HTML markup + FastSpring script setup:

<!-- Optional: Element used to show the returned webhook data -->
<div id="callback-status-message">Waiting for popup webhook...</div>

<!-- Button to launch the FastSpring checkout popup -->
<button onclick="fastspring.builder.checkout()">Checkout</button>

<!-- Load the Store Builder with the popup webhook callback -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-URL"
  data-popup-webhook-received="dataPopupWebhookReceived"
  data-continuous="true">
</script>

<!-- Preload cart contents for demo purposes -->
<script>
  fastspring.builder.reset();
  fastspring.builder.add("your-product-path");
</script>

JavaScript callback function:

function dataPopupWebhookReceived(data) {
  const status = document.getElementById("callback-status-message");
  if (status) {
    status.innerHTML = "<pre>" + JSON.stringify(data, null, 4) + "</pre>";
  }
}

What it does:
This callback fires when FastSpring receives a webhook during the popup flow (e.g., after a purchase). It’s useful for capturing real-time purchase data while the popup is still open.

What to update:

  • Replace your-product-path with a product from your store.
  • Replace your-storefront-URL with the full path to your storefront’s checkout.
  • Rename dataPopupWebhookReceived if needed for your use case.

FAQs

What if my callback isn't firing?

Make sure the callback function is defined in the global scope and loaded before the Store Builder script finishes initializing. Also check that the function name exactly matches the one used in your data-* attribute.

Can I define multiple callbacks in the same script?

Yes. You can define as many callback functions as you need, as long as each one has a unique name and is referenced properly in your HTML.

Do I need to remove callbacks in production?

No, callbacks are safe for development and production environments. However, it's a good idea to remove data-debug and any console.log() calls before deploying your final site.