Integrating Tools and Scripts in Motive
Last updated: December 15, 2025
Background
The Motive platform is built as a Single Page Application (SPA). Changes to the viewed page do not always mean the page is reloaded. When a user navigates between pages, e.g. from the SRP to the VDP, the DOM is updated in the places needed to show the VDP rather than replacing the whole page. As a result, the side effects of a full page reload cannot be relied on:
DOMContentLoadeddoes not fire when the route changes on SPA’s. It cannot be fired manually. This is a common event for scripts to hook into and expect to see for every page change.Web History API events are not guaranteed to fire. Since SPA’s handle routing internally, events like
popstatemay not fire for every page change. This is another common event script’s hook to.
This document describes symptoms of an integration that is incompatible with SPA’s, and a few options for working with SPA’s and more specifically Motive.
Symptoms of Tools/Scripts lacking SPA support
The tool only works when reloading the page
e.g. When a user goes from SRP → VDP, the tool’s CTA button is missing. When refreshing the VDP, the tool’s CTA button loads and works as expected.
The user must press the browser back button several times to leave a page
e.g. If the user is on a VDP and clicks a button that triggers an iframe to open, the user will have to press the back button 2+ times to go back to the SRP
This happens most with tools that inject iframes into the page, which can manipulate history. This causes conflicts with how SPA’s manage history. This usually requires more work to fix than what is described below.
The tool has outdated information when changing between pages
e.g. A User on a VDP might see copy inside of a tool’s CTA that is specific to a brand. Upon navigation to another VDP, that copy does not update when it should.
Integrating with Motive
If your tool is already built for SPA’s, it will likely work out of the box. If the previously described symptoms are evident, it is likely that the tool is not built for SPA’s and will need some changes to work appropriately. While we do our best to make integrating with Motive as easy as possible, some things (e.g. hooking a script’s logic to the DOMContentLoaded event) are incompatible with SPA’s given that route changes ≠ a reload.
The following are options for making your script work on Motive in order of ease, preference, and performance:
Event Listener
This is the most performant and reliable approach for both parties when integrating a script onto Motive.
Motive fires an Event named page-change through custom DOM events every time the page changes. This is true for all Motive sites. This can be “hooked” into to perform some work. A simple example might look something like the following:
window.addEventListener("page-change", YOUR_CALLBACK_FUNCTION);This adds an event listener for our page-change event, which then runs a callback function. Replace YOUR_CALLBACK_FUNCTION with an appropriate function for the tool. The callback is likely a function that already exists inside the script, making it generally simple to implement. This callback could do something like:
Search for a target div on the page to populate with a button (a common pattern)
Fire events related to page change for analytics or internal use of the tool
Re-init the script (best if this is avoidable, as it can have performance implications and unnecessarily re-fetch assets used by the tool)
Adding an event listener is the preferred approach as it requires the least amount of work from both parties involved and is capable of being the most performant. Adding it to your tool/script does not interfere with other functions of the script and has a very low performance and implementation overhead.
Expose Tool API
This is typically used for deeper and more native looking integrations, but generally requires more work from both parties which can be undesirable when the goal is the quickest implementation possible.
Many scripts rely on functions defined inside their own scope, however if these functions are exposed globally, Motive can use these given enough documentation on them is provided. This allows native buttons to be used on the site, preserving visual cohesion and OEM compliance while allowing the script to perform needed functions without re-initialization.
Internal script function’s can have their API exposed globally by creating a global namespace/object that functions exist upon, or adding them to the window directly. We recommend the former approach to avoid polluting the global namespace, as this may cause the script to break other scripts or visa versa. A simple example for exposing your API for use via a global namespace might look like the following:
/* Add the functions you want Motive to be able to call */
window.TOOL_NAME = {
api: {
openTool: function(vin) {
...
}
}
};Inside Motive, the API then might be used like the following:
/* JavaScript */
function activateTool() {
TOOL_NAME.api.openTool(vehicle.vin)
}
/* HTML */
<button onclick="activateTool()">
Click this CTA!
</button>While this approach provides the most native looking integration, it usually requires developer work from both parties. If the API is not yet available globally and/or documented, it requires the script provider to do such things. Conversely, Motive must implement the integration into existing buttons which may take more or less time depending upon integrations currently being worked on, integration depth, and different dealer use cases - among other things.
Mutation Observer
We do not recommend this approach if a script is not already built to be compatible with SPA’s, as it can be performance heavy and prone to edge-cases. This is a common approach for existing SPA friendly scripts/tools as it is the most universal at the cost of being more complex to implement and prone to being inefficient. Since Motive is an SPA, the DOM changes frequently while users navigate and use the website, meaning the mutation observer can fire rather frequently.
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver