muro is not defined
Fix errors like "muro is not defined" or "Cannot read properties of undefined (reading 'track')" when sending custom events.
window.muro only exists once muro.js has loaded and run. If your code calls window.muro.track() before then, or on a page where the script can't run, you get an error like one of these:
ReferenceError: muro is not definedTypeError: Cannot read properties of undefined (reading 'track')Property 'muro' does not exist on type 'Window'(TypeScript)
Why it happens
- The script hasn't run yet.
muro.jsloads withasync, so it runs as soon as it's downloaded, which can be after your own code. Muro has no queue for calls made before it loads. - The script was blocked. Ad blockers, privacy extensions, some networks and a strict Content Security Policy can stop it from loading at all.
window.murothen never exists for that visitor. - The tag has no
data-project-id. Without a project ID the script stops straight away and doesn't createwindow.muro. - The code runs on the server. In Next.js, Astro and other frameworks with server rendering, code outside the browser has no
window.
Fix it
Use optional chaining
Call track like this everywhere:
window.muro?.track('signup');If Muro hasn't loaded, or never will for this visitor, the call is skipped quietly and your page keeps working. This is the recommended pattern.
Track clicks without JavaScript
For buttons and links, skip the JavaScript and add an attribute instead:
<button data-muro-event="signup">Sign up</button>A click on the element, or anything inside it, sends a custom event named signup. It works for elements added later and across single-page-app navigations, and it can't throw. It doesn't send properties. See Track custom events.
Call track from the browser only
In React, Next.js and similar frameworks, call track from event handlers or effects, which only run in the browser:
'use client';
export function SignupButton() {
return (
<button onClick={() => window.muro?.track('signup')}>
Sign up
</button>
);
}Don't call it at the top level of a module or in a server component.
Add a TypeScript declaration
TypeScript doesn't know about window.muro until you declare it. Add this to a .d.ts file in your project, such as muro.d.ts:
export {};
declare global {
interface Window {
muro?: {
track: (
name: string,
props?: Record<string, string | number | boolean>
) => void;
};
}
}Marking muro as optional makes TypeScript remind you to use ?..
Events that must fire on page load
For an event you want to send as soon as a page opens, for example on a thank-you page, wait for the script to load:
function trackWhenReady(name, props) {
if (window.muro) return window.muro.track(name, props);
var tag = document.querySelector('script[src*="api.muroanalytics.com/muro.js"]');
if (tag) tag.addEventListener('load', function () { window.muro?.track(name, props); });
}
trackWhenReady('purchase_complete');If all you need is to count visits to a page, you don't need an event at all. Create a Page goal for its path instead. See Set up goals.
Verify it works
- Open your site with DevTools → Console open. Type
window.muroand press Enter. You should see an object with atrackfunction. - Trigger your event. The Console shows no errors.
- In Network, filtered to
collect, a request with"event_type":"custom"and your event name appears with status202. - The event appears in the dashboard's Custom Events panel.