{"id":19294707,"url":"https://github.com/moesif/moesif-browser-js","last_synced_at":"2026-04-02T00:03:28.569Z","repository":{"id":17050108,"uuid":"80966244","full_name":"Moesif/moesif-browser-js","owner":"Moesif","description":"Javascript Client side Library for Moesif Integration","archived":false,"fork":false,"pushed_at":"2024-08-24T03:26:53.000Z","size":6408,"stargazers_count":14,"open_issues_count":24,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-15T12:49:47.836Z","etag":null,"topics":["analytics","api","logging","moesif","restful"],"latest_commit_sha":null,"homepage":"https://www.moesif.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Moesif.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-05T03:31:37.000Z","updated_at":"2023-12-18T09:26:30.000Z","dependencies_parsed_at":"2023-11-28T07:28:17.662Z","dependency_job_id":"d8a54070-216f-41e3-a316-72abb1efb640","html_url":"https://github.com/Moesif/moesif-browser-js","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-browser-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-browser-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-browser-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moesif%2Fmoesif-browser-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Moesif","download_url":"https://codeload.github.com/Moesif/moesif-browser-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250205978,"owners_count":21392159,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","api","logging","moesif","restful"],"created_at":"2024-11-09T22:39:20.545Z","updated_at":"2026-04-02T00:03:28.507Z","avatar_url":"https://github.com/Moesif.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Moesif JavaScript Browser SDK\n\n[![NPM](https://nodei.co/npm/moesif-browser-js.png?compact=true\u0026stars=true)](https://nodei.co/npm/moesif-browser-js/)\n\n[![Built For][ico-built-for]][link-built-for]\n[![Total Downloads][ico-downloads]][link-downloads]\n[![Software License][ico-license]][link-license]\n[![Source Code][ico-source]][link-source]\n\nThe Moesif browser SDK enables you to identify users and track their website behavior to understand user journeys across your website and APIs together. This SDK also captures device context like geo location, browser version, marketing channel attribution, and UTM parameters.\n\n\u003e You can use this client SDK alongside a [Moesif server integration](https://www.moesif.com/implementation) to monitor server-side API traffic. This enables you to track your end-to-end customer journey and build cross-platform funnel reports like your _initial sign up_ to _first API call_ conversion rate.\n\n![Diagram of Moesif API monitoring and Browser JS architecture](https://www.moesif.com/docs/images/docs/client-integration/moesif-arch-browser-js.png)\n\nThe SDK automatically collects useful context from a user's device including any marketing attribution, device type, and location information and stores in the user and/or company profile in Moesif. You can add additional customer properties such as user email and company domain via the `identifyUser()` and `identifyCompany()` methods.\n\nIf you want to automatically log AJAX API calls, you can also call the `start()` method. API logging has native support for RESTful, GraphQL, Ethereum Web3, JSON-RPC, and other APIs\n\n[Source Code on GitHub](https://github.com/moesif/moesif-browser-js)\n\n## How to install\n\n\u003e This SDK is designed to run in a browser. To monitor Node.js APIs, use [moesif-nodejs](https://www.moesif.com/docs/server-integration/nodejs/).\n\n### Installation via script tag\n\n```html\n\u003cscript src=\"//unpkg.com/moesif-browser-js@v1/moesif.min.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\"\u003e\n  // Initialize the SDK. Must be called before any other methods\n  moesif.init({\n    applicationId: \"Your Publishable Moesif Application Id\",\n    // add other option here\n  });\n\n  // Identify the user with Moesif such as when user logs in\n  moesif.identifyUser(\"12345\");\n\n  // Log user actions like clicked sign up. You can also pass in custom metadata.\n  moesif.track(\"clicked_sign_up\", {\n    button_label: \"Get Started\",\n  });\n\u003c/script\u003e\n```\n\nPut the above script tags in between the `\u003chead\u003e` tags of your HTML page.\nIt will attach a global `moesif` object. You can access it either via `moesif` or `window.moesif`.\n\n### Alternative installation via NPM\n\nThe SDK is also available on [NPM](https://www.npmjs.com/package/moesif-browser-js) which can be used if you're using\na front-end packager like [Browserify](http://browserify.org/) or [Webpack](https://webpack.github.io/):\n\n```sh\nnpm install --save moesif-browser-js\n```\n\nYou can then require the lib like a standard NPM module:\n\n```javascript\nvar moesif = require(\"moesif-browser-js\");\n// or using the import syntax\n// import moesif from \"moesif-browser-js\";\n\n// Initialize the SDK. Must be called before any other methods\nmoesif.init({\n  applicationId: \"Your Publishable Moesif Application Id\",\n  // add other option here\n});\n\n// Identify the user with Moesif such as when user logs in\nmoesif.identifyUser(\"12345\");\n\n// Log UI actions like clicked sign up\nmoesif.track(\"clicked_sign_up\", {\n  button_label: \"Get Started\",\n});\n```\n\nWith the `require` method, the `moesif` object is not attached to any global scope, but you can attach to the global window object easily:\n\n```javascript\nwindow.moesif = moesif;\n```\n\n\nYour Publishable Moesif Application Id will be displayed during the onboarding steps when signing up for [Moesif](https://www.moesif.com/) when you select Browser JS. You can always find your Publishable Moesif Application Id at any time by logging\ninto the [_Moesif Portal_](https://www.moesif.com/), go to the main menu,\nand then clicking _Installation_.\n\n\u003e You should only use your __publishable__ application id in untrusted apps like client-side javascript. This can be found by logging into Moesif and clicking API Keys from the bottom left menu.\n\n## How to use\n\n### Track user actions\n\nActions are something that a user (or company) performed on your website such as \"Clicked Sign Up\", \"Viewed Documentation\", or \"Purchased a Plan\".\nBesides the action name, you can also save related metadata properties such as the \"Sign Up Method\" or \"Button Label\".\n\n```javascript\n// The first argument is required and contains the action name as a string.\n// The second argument is optional and contains custom event metadata such as button label.\nmoesif.track('Clicked Sign Up', {\n  button_label: 'Get Started',\n  sign_up_method: 'Google SSO'\n});\n```\n\nMoesif recommends starting with the following actions: \"Viewed Landing\", \"Viewed Docs\", \"Account Created\", \"Signed Up\", \"Signed In\", \"Invite Sent\", \"Started Onboarding\", \"Finished Onboarding\", \"Trial Started\", and \"Trial Ended\".\n\n### Identifying users\n\nWhen you know the user's id such as after sign in, call `identifyUser`.\nThis tells Moesif who the current user is so their actions can be linked to a user profile.\n\nBesides the userId, you can also save related properties such as user demographics and subscription information.\n\n```javascript\nmoesif.identifyUser(\"12345\", {\n  email: \"john@acmeinc.com\",\n  firstName: \"John\",\n  lastName: \"Doe\",\n  title: \"Software Engineer\",\n  salesInfo: {\n    stage: \"Customer\",\n    lifetimeValue: 24000,\n    accountOwner: \"mary@contoso.com\",\n  },\n});\n```\n\nMoesif recommends against calling `identifyUser` for anonymous users. Moesif will track these users automatically.\nThe recommended place to call `identifyUser` is after the user logs in and you know their real user id.\n\n### Identifying companies\n\nIn addition to identifying users, you can also identify the company for account level tracking. Besides the companyId, you can also save related properties such as company demographics and website domain.\n\n```javascript\n// Only the first argument is a string containing the company id. This is the only required field.\n// The second argument is a object used to store a company info like plan, MRR, and company demographics.\n// The third argument is a string containing company website or email domain. If set, Moesif will enrich your profiles with publicly available info.\nmetadata = {\n  orgName: \"Acme, Inc\",\n  planName: \"Free Plan\",\n  dealStage: \"Lead\",\n  mrr: 24000,\n  demographics: {\n    alexaRanking: 500000,\n    employeeCount: 47,\n  },\n};\n\nmoesif.identifyCompany(\"67890\", metadata, \"acmeinc.com\");\n```\n\n\u003e If you call both identifyUser() and identifyCompany() in the same session, then Moesif will automatically associate the user with the company.\n\n### Track AJAX calls\nIf you want to automatically log AJAX API calls, you can do so via the `start` function.\n\n```javascript\n// Start capturing AJAX API Calls.\nmoesif.start();\n```\n\n## Anonymous Ids\n\nWhen moesif-browser-js is initialized, an `anonymousId` is generated and stored for each new visitor.\nThis enables you to create funnel reports of anonymous visitors even before they have signed in\n\nOnce a user signs into your app, you should call `identifyUser`.\nMoesif will automatically merge any previous user activity to the real userId, even if it's a new device.\n\n\u003e You should call `moesif.reset()` when a user logs out of your application to ensure a new anonymousId is generated. Otherwise, new activity may get associated with an old user session.\n\n**You should only call `identifyUser` once a user logs into your app. Do not call `identifyUser` for anonymous visitors.**\n\nBy default, Moesif uses both local storage and cookies for redundancy, but you can modify this behavior with the `persistence` options\n\n## Cross-Domain Tracking\n\nBy default, anonymous user sessions are scoped to a single domain (including sub-domains). If your product spans multiple domains (e.g., `example.com` and `hello.world.dev`), each domain gets its own independent `anonymousId`, making it impossible to stitch together the full user journey.\n\n**Cross-Domain Tracking (CDT)** is an opt-in feature that passes the `anonymousId` between domains via a URL query parameter. When a user navigates from one domain to another, the SDK appends the current `anonymousId` to outgoing links. Upon arrival at the destination site, the SDK reads the parameter, persists the ID, and removes the parameter from the address bar to keep URLs clean.\n\n\u003e For CDT to work end-to-end, **both** the origin domain and the destination domain must have `enableCrossDomainTracking: true` configured in their `moesif.init()` call.\n\n### Basic setup\n\n```javascript\nmoesif.init({\n  applicationId: \"Your Publishable Moesif Application Id\",\n  enableCrossDomainTracking: true,\n  crossDomainTargets: null,             // null = decorate all cross-domain links\n  // crossDomainTargets: [\"site1.com\", \"site2.com\"],  // or restrict to specific domains\n  // crossDomainTrackingParameterName: '__mt',        // optional: customise the query param name (default: __mt)\n});\n```\n\n\u003e **Important:** If `crossDomainTargets` is omitted entirely (i.e. not set), **no** cross-domain links will be decorated. You must explicitly set it to `null` (all domains) or an array of target domains to activate URL decoration. This is intentional — it prevents unexpected behavior from silent defaults.\n\n### Configuration options\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `enableCrossDomainTracking` | boolean | `false` | Enables or disables Cross-Domain Tracking. |\n| `crossDomainTargets` | `null` \\| `string[]` | *(unset — no decoration)* | `null` decorates all cross-domain links. An array restricts decoration to only those domains. If the option is not set, no links are decorated. |\n| `crossDomainTrackingParameterName` | string | `__mt` | The URL query parameter name used to carry the `anonymousId`. |\n\n### Automatically intercepted navigations\n\nWhen CDT is enabled, the SDK automatically decorates outgoing URLs for the following navigation methods:\n\n- **Anchor tags** (`\u003ca href=\"...\"\u003e`) — standard clicks, middle-clicks, touch events, and \"Copy Link Address\" via the context menu.\n- **Form submissions** — GET method only. POST form actions are not decorated.\n\n### Manual URL decoration\n\nSome navigation methods cannot be intercepted automatically (e.g., `window.location.href`, `window.location.assign()`, `window.location.replace()`, `window.open()`, and the Navigation API). For these cases, the SDK exposes a helper:\n\n```javascript\nmoesif.cdtUrlDecorator(targetURL, overrideCDTTargets = false)\n```\n\nThis function appends the current `anonymousId` and the configured parameter name to the given URL. If the URL is already decorated, the existing parameter value is updated. If the target domain is not in `crossDomainTargets`, the URL is returned unchanged — unless `overrideCDTTargets` is set to `true`.\n\n**Example usage:**\n\n```javascript\n// Anchor tags are handled automatically. For JS-based redirects, wrap the URL manually:\n\n// window.location.href\nwindow.location.href = moesif.cdtUrlDecorator('https://console.bijira.dev/signup');\n\n// window.location.assign\nwindow.location.assign(moesif.cdtUrlDecorator('https://console.bijira.dev/signup'));\n\n// window.location.replace\nwindow.location.replace(moesif.cdtUrlDecorator('https://console.bijira.dev/signup'));\n\n// window.open\nwindow.open(moesif.cdtUrlDecorator('https://console.bijira.dev/signup'));\n\n// Navigation API\nnavigation.navigate(moesif.cdtUrlDecorator('https://console.bijira.dev/signup'));\n\n// Force-decorate a URL regardless of crossDomainTargets\nconst url = moesif.cdtUrlDecorator('https://other-domain.com/page', true);\n```\n\nA convenience wrapper pattern if `moesif` may not yet be initialised:\n\n```javascript\nfunction decorateMoesifCdtUrl(url) {\n  if (moesif) {\n    return moesif.cdtUrlDecorator(url);\n  }\n  return url;\n}\n```\n\n### How it works\n\n1. User visits `site-a.com` — the SDK generates and stores an `anonymousId`.\n2. User clicks a link to `site-b.com` — the SDK appends `?__mt=\u003canonymousId\u003e` to the URL.\n3. User lands on `site-b.com` — the SDK reads `__mt`, persists the same `anonymousId`, and removes the parameter from the address bar.\n4. Both sites now share the same `anonymousId`, so all actions across both domains are stitched into one continuous user journey in Moesif.\n\n\u003e Same-domain links are never decorated — URL decoration only occurs when the destination is a different domain than the current page.\n\n---\n\n\n## Consent Management\n\nThe Moesif SDK provides flexible consent management options to help you comply with privacy regulations like GDPR and CCPA. The SDK distinguishes between **consent to store data locally** and **consent to publish data to Moesif servers**.\n\n### Important: Cookies Created on Init\n\n**⚠️ Cookies and localStorage may be created as soon as the SDK is initialized (`init()`), regardless of the user's consent status.**\n\nIf your compliance requirements mandate that **no cookies or storage are created before consent is obtained**, you must:\n1. **Defer SDK initialization** until after the user grants consent\n2. **Call `moesif.init()`** only after consent is granted\n\nThis is the recommended approach for strict \"consent-first\" implementations where no tracking data can be stored locally before user consent.\n\n### Consent for Publishing (`requirePublishingConsent`)\n\nIf you want to **track user actions locally without sending data to Moesif until consent is granted**, use the `requirePublishingConsent` option. This approach allows you to:\n\n- Track all user actions and API calls without any loss of data\n- Store tracked events locally in a queue (persisted to localStorage only, NOT cookies)\n- Automatically flush the queue to Moesif when consent is granted\n- Continue tracking seamlessly across page refreshes (when using default `localStorage` persistence mode)\n\nThis is ideal when you want **zero data loss** while still respecting user privacy - all events are tracked locally and sent to Moesif only after the user explicitly consents.\n\n### How It Works\n\nWhen `requirePublishingConsent: true` is set:\n\n1. **Before Consent:**\n   - All `track()` calls, `identifyUser()`, `identifyCompany()`, and API events are queued locally\n   - Queue is persisted to **localStorage only** (not on cookies) and survives page refreshes\n   - **Note:** If `persistence: 'cookie'` mode is used, the queue will NOT persist across page refreshes (in-memory only)\n   - Cross-domain tracking links are NOT decorated (no anonymousId in URLs)\n   - Queue follows FIFO (First-In-First-Out) - oldest events dropped when limit reached\n\n2. **After `grantPublishingConsent()` is called:**\n   - All queued events are immediately sent to Moesif\n   - Local queue is cleared after successful delivery\n   - Future events are sent to Moesif immediately\n   - Cross-domain tracking links are decorated with anonymousId\n\n3. **After `revokePublishingConsent()` is called:**\n   - Consent state is revoked\n   - Any queued events are cleared\n   - New events start queuing locally again\n\n4. **Recording Control with [`start()`](#start--null) and [`stop()`](#stop--null):**\n   - These methods work the same way as described in their respective documentation, the only difference is when consent is not granted, events are queued up locally instead of being sent immediately to Moesif.\n   - See [`start()`](#start--null) and [`stop()`](#stop--null) for full details\nRefer [API Methods](#list-of-methods-on-the-moesif-object) for details on each methods.\n\n### State Management: Developer Responsibility\n\n**⚠️ Important:** The SDK does **NOT** persist the following states:\n- Whether `init()` has been called\n- Whether consent has been granted via `grantPublishingConsent()`\n\nYou (the developer) are responsible for:\n1. **Managing initialization state** - Track whether you've called `init()`\n2. **Managing consent state** - Store the user's consent decision in your own storage\n3. **Restoring state on page load** - Check your stored consent state and call `grantPublishingConsent()` if needed\n\n#### Example: State Management Implementation\n\n```javascript\n// On page load\ndocument.addEventListener('DOMContentLoaded', function() {\n  // Initialize SDK (this creates cookies/localStorage)\n  moesif.init({\n    applicationId: 'Your Publishable Moesif Application Id',\n    requirePublishingConsent: true\n  });\n\n  // Check your stored consent state (example using localStorage)\n  const hasConsented = localStorage.getItem('user_tracking_consent') === 'granted';\n\n  if (hasConsented) {\n    // User previously granted consent, restore it\n    moesif.grantPublishingConsent();\n  }\n\n  // Start tracking API calls and user actions\n  moesif.start();\n});\n\n// When user grants consent\nfunction handleConsentAccepted() {\n  // Store consent decision in YOUR storage\n  localStorage.setItem('user_tracking_consent', 'granted');\n\n  // Grant consent in Moesif SDK\n  moesif.grantPublishingConsent();\n}\n\n// When user revokes consent\nfunction handleConsentRevoked() {\n  // Update consent decision in YOUR storage\n  localStorage.setItem('user_tracking_consent', 'revoked');\n\n  // Revoke consent in Moesif SDK\n  moesif.revokePublishingConsent();\n}\n```\n\n### Example: Complete Consent Flow\n\n```javascript\n// 1. Initialize with consent required\nmoesif.init({\n  applicationId: 'Your Publishable Moesif Application Id',\n  requirePublishingConsent: true,\n  maxQueueSize: 1000\n});\n\n// 2. Start recording (events will be queued, not sent)\nmoesif.start();\n\n// 3. Track events (queued locally)\nmoesif.track('viewed_homepage');\nmoesif.identifyUser('user_123');\n\n// 4. When user grants consent\nmoesif.grantPublishingConsent();\n// Now all queued events are sent to Moesif\n\n// 5. Continue tracking (sent immediately)\nmoesif.track('clicked_cta');\n\n// 6. If user later revokes consent\nmoesif.revokePublishingConsent();\n// Future events will be queued again (not sent)\n```\n\n### Strict Compliance Mode: Defer Init Until Consent\n\nFor strict compliance where **no cookies or storage can be created before consent**:\n\n```javascript\n// Wait for user consent before initializing\ndocument.addEventListener('DOMContentLoaded', function() {\n  // Check if user has already granted consent\n  const hasConsented = localStorage.getItem('user_tracking_consent') === 'granted';\n\n  if (hasConsented) {\n    // User previously consented, safe to initialize\n    initializeMoesif();\n  } else {\n    // Show consent banner\n    showConsentBanner();\n  }\n});\n\nfunction initializeMoesif() {\n  moesif.init({\n    applicationId: 'Your Publishable Moesif Application Id'\n  });\n  moesif.start();\n\n  // Track events immediately (they go to Moesif right away)\n  moesif.track('session_started');\n}\n\nfunction handleConsentAccepted() {\n  localStorage.setItem('user_tracking_consent', 'granted');\n  initializeMoesif(); // Initialize only after consent\n  hideConsentBanner();\n}\n```\n\n## List of Methods on the `moesif` Object\n\n#### init, (obj) =\u003e null\n\nInitialize the SDK with your Publishable Application Id and any other options.\nOn initialization, the SDK will capture user context like device and marketing attribution.\nThis method must be called before any other methods like `start()` or `identifyUser`.\n\n```javascript\nvar options = {\n  applicationId: 'Your Publishable Moesif Application Id'\n};\n\nmoesif.init(options);\n\n```\n\n#### identifyUser, (string, object) =\u003e null\n\nWhen a user logs into your website and you have their actual user id, identify the user with your userId.\nYou can also add custom metadata containing fields like the customer's name and email as the second argument.\n\nNote: You shouldn't call `identifyUser` for anonymous visitors to your website.\nMoesif automatically assigns them an anonymousId, so just calling track works just fine without identify.\n\nWhen you call identifyUser, Moesif automatically merges the anonymousId with your real userId.\n\n```javascript\nmoesif.identifyUser(\"12345\", metadata);\n```\n\n#### identifyCompany, (string, object, string) =\u003e null\n\nSimilar to `identifyUser`, but for tracking companies (accounts) which is recommended for B2B companies.\nYou can use both `identifyUser` and `identifyCompany` or just one. If you call both identifyUser() and identifyCompany() in the same session, then Moesif will automatically associate the user with the company.\n\nOnly the first argument is a string containing the company id. This is the only required field.\nThe second argument is a object used to store a company info like plan, MRR, and company demographics.\nThe third argument is a string containing company website or email domain. If set, Moesif will enrich your profiles with publicly available info.\n\n```javascript\nmoesif.identifyCompany(\"67890\", metadata, \"acmeinc.com\");\n```\n\n#### track, (string, object) =\u003e null\n\nTrack user actions such as \"clicked sign up\" or \"made a purchase\". By tracking user actions in addition to API usage via one of the [Moesif server SDKs](https://www.moesif.com/implementation), you'll be able to understand the entire customer journey from initial sign up to first API call. First argument is an action name as a string, which is required. Second parameter is an optional metadata object related to this action event. [See API Reference](https://www.moesif.com/docs/api#track-a-user-action)\n\n```javascript\nmoesif.track('clicked_sign_up', {\n  button_label: 'Get Started'\n});\n```\n\n#### identifySession, (string) =\u003e null\n\nThe Moesif SDK tracks browser sessions automatically and saves in a Cookie. You can override with a specific session token.\n\nThe new session token will continue to be used until `identifySession` is called again.\n\n```javascript\nmoesif.identifySession(\"d23xdefc3ijhcv93hf4h38f90h43f\");\n```\n\n#### reset, () =\u003e null\n\nClears any saved userId, companyId, and any other device context like anonymousId.\nYou must call `reset()` when a user logs out of your web app which will force the SDK to generate a new anonymousId.\nThis ensures a new anonymous id is generated and ensuring different sessions are not mixed up.\n\nThis is especially important for testing if you are logging into multiple accounts from the same device.\n\n```javascript\nmoesif.reset()\n```\n\n#### start, () =\u003e null\n\nIn addition to tracking user actions, the SDK can also log outgoing API calls.\nWhen you call `start()`, the SDK will log AJAX API calls, including:\n\n- Your own APIs (such as an API powering your Single Page App)\n- 3rd party APIs (such as to Stripe and Twilio)\n- Decentralized APIs such as DApps communicating with Ethereum Web3/interactions with smart contracts\n\n```javascript\nmoesif.start()\n```\n\n#### stop, () =\u003e null\n\nStops logging AJAX API calls. It is not required to call this, since recording will stop automatically when the browser tab is closed.\nHowever, you can call `stop` directly if you want more control. Call `start` again to restart API logging.\n\n```javascript\nmoesif.stop()\n```\n\n#### cdtUrlDecorator, (string, boolean) =\u003e string\n\nManually decorates a URL with the current `anonymousId` for use with navigation methods that cannot be intercepted automatically (e.g., `window.location.href`, `window.open()`). Requires `enableCrossDomainTracking: true` in `init()`.\n\nThe second argument `overrideCDTTargets` (default `false`) forces decoration even if the target domain is not in `crossDomainTargets`.\n\nReturns the decorated URL as a string. If the target domain is not allowed and `overrideCDTTargets` is false, the original URL is returned unchanged.\n\n```javascript\nconst decoratedUrl = moesif.cdtUrlDecorator('https://console.bijira.dev/signup');\nwindow.location.href = decoratedUrl;\n```\n\n#### useWeb3, (web3) =\u003e boolean\n\nSets the web3 JSON-RPC to use the web3 object passed in. If no argument is passed\nin, it will try to restart capturing using the global `web3` object. Return `true` if successful.\n\n```javascript\nmoesif.useWeb3(myWeb3Object);\n```\n\n#### grantPublishingConsent, () =\u003e void\n\nCall this method when the user grants consent to send data to Moesif. This will:\n- Flush all queued events to Moesif servers\n- Clear the local queue after successful delivery\n- Allow future events to be sent immediately\n\n```javascript\n// When user clicks \"Accept Cookies\" or \"Accept Tracking\"\nmoesif.grantPublishingConsent();\n```\n\nRefer [Consent Management](#consent-management) more details.\n\n#### revokePublishingConsent, () =\u003e void\n\nCall this method when the user revokes consent. This will:\n- Stop sending new events to Moesif\n- Clear any queued events\n- Start queuing new events locally again (if recording is active)\n\n```javascript\n// When user clicks \"Revoke Consent\" or \"Opt Out\"\nmoesif.revokePublishingConsent();\n```\nRefer [Consent Management](#consent-management) more details.\n\n#### isPublishingConsentGranted, () =\u003e boolean\n\nReturns `true` if consent to publish has been granted, `false` otherwise.\n\n```javascript\nif (moesif.isPublishingConsentGranted()) {\n  console.log('User has granted consent to publish data');\n} else {\n  console.log('User has not granted consent yet');\n}\n```\nRefer [Consent Management](#consent-management) more details.\n\n\n## Configuration options\n\nThe `options` is an object that is passed into the SDK's `init` method.\n\n#### applicationId - string, required\n\nThis is the collector API key that is obtained from your Moesif account. You should only use your publishable application id in untrusted apps like client-side javascript. Publishable Collector Application Id's are write-only keys and can be safely used on the client side.\n\n#### enableCrossDomainTracking, boolean, optional, default false\n\nEnables Cross-Domain Tracking (CDT). When `true`, the SDK will automatically decorate outgoing cross-domain anchor links and GET form submissions with the current `anonymousId`. Use `cdtUrlDecorator()` for JS-based navigations that cannot be intercepted automatically.\n\nBoth the origin and destination sites must have this option enabled for tracking to be stitched together correctly.\n\n#### crossDomainTargets, null | string[], optional, default: unset (no decoration)\n\nControls which destination domains will have their URLs decorated with the `anonymousId`.\n\n- **`null`** — decorate all outgoing cross-domain links.\n- **`[\"domain-a.com\", \"domain-b.com\"]`** — only decorate links pointing to the listed domains.\n- **Unset (not provided)** — no cross-domain links are decorated. You must explicitly set this option to `null` or a non-empty array to activate URL decoration.\n\n#### crossDomainTrackingParameterName, string, optional, default `__mt`\n\nThe URL query parameter name used to carry the `anonymousId` between domains. Override this if `__mt` conflicts with an existing parameter in your application.\n\n#### batchEnabled, boolean, optional, default false.\n\nWill start batching the tracking of API Events and User Actions to sent to Moesif. The identifyUser and identifyCompanies are not batched.\n\n#### batchSize, number, optional, default 25\n\nEven if set, the batchSize is used on a best effort basis. If the payloads sizes get too big, the batchSize maybe auto adjusted.\n\n#### batchMaxTime, number in milliseconds, optional, default 2500\n\nThe maximum interval to flush the queue when the batch size have not been reached.\n\n#### eagerBodyLogging, boolean, optional, default false\n\nSome complex frameworks like Angular monkey patch to intercept the response body. If you are an Angular user or find that the response is not being captured, turn this option on to eagerly capture the response info.\n\n#### persistence, string, optional, default localStorage\n\nThe allowed values are `localStorage`, `cookie`, and `none`.\n\nMoesif saves session info like anonymous ids and identified ids to a device's storage to accurately track returning visitors even if they haven't signed in.\n\n* When set to `localStorage` (the default setting), will write session info to localStorage and then replicate to a cookie for redundancy.\nThis ensures that if the user clears local storage or visits a different subdomain (like from `docs.acmeinc.com` to `acmeinc.com`), there is still\na cookie to fall back to and the user can be accurately attributed. This setting is recommended for most applications.\n\n* When set to `cookie`, session info and anonymous ids is persisted to cookies only. No local storage is used.\n**Note:** If you're using the `requirePublishingConsent` feature, the pending events queue will NOT persist across page refreshes in this mode (stored in-memory only).\n\n* When set to `none`, nothing will be persisted. Not recommended except for advanced use cases or testing. Refreshing the browser tab will create a new user session.\n**Note:** The pending events queue (when using `requirePublishingConsent`) will also not persist across page refreshes in this mode.\n\nKeep in mind if a user clears both their cookies and their local storage, then a new `anonymousId` will be generated,\nAs long as you called `identifyUser` before the data was cleared, Moesif will still merge the two sessions.\n\n#### crossSiteCookie, boolean, optional, default false,\n\nThis enables [cross-site requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) by adding `SameSite=None; Secure` to the cookie.\nThis is used for special situation such as if your application is embedded in an iframe.\n\n\u003e When enabled, `secureCookie` is forced to true due to modern browser requirements.\n\n#### crossSubdomainCookie, boolean, optional, default true,\nWhen true, the cookie domain will also allow all subdomains of your hostname. This is usually recommended to track anonymous users across multiple\nproperties like `https://www.acmeinc.com` vs `https://docs.acmeinc.com`.\n\n#### cookieExpiration, number, optional, default 365\nSet the cookie expiration in days. By default this is 365 days.\n\n#### secureCookie, boolean, optional, default false,\nIf set to true, the cookie can only be read on `https://` websites.\n\n#### cookieDomain, string, optional, default ''\nTo override the domain of the cookie, you can set this such as to `*.acmeinc.com`\n\n#### persistenceKeyPrefix, string, optional, default moesif_\nThe keys used for saving into local storage and cookies start with `moesif_`. You can override the prefix such as if you're running multiple instances of `moesif-browser-js`.\n\n#### disableFetch, boolean, optional, default false.\n\nStarting from version 1.4.0, this SDK also instruments fetch API if it is not polyfilled.\nSome browsers may use fetch under `XmlHTTPRequest`, then it is possible events get duplicated. In this case, disable fetch will fix the issue.\n\n#### skip, (event) =\u003e boolean, optional\n\nA function hook that will skip logging the event to Moesif if returns true.\nThe parameter passed in is an event model. [See event model](https://www.moesif.com/docs/api#log-an-api-call).\n\n_High volume APIs can reduce cost tremendously by leveraging [dynamic sampling](https://www.moesif.com/docs/platform/dynamic-sampling/) to set rules\nwithout any code change or restarts. Moesif will still extrapolate original metrics so your reporting is accurate._\n\n#### maskContent, (event) =\u003e event, optional\n\nA function hook that enables you to mask any sensitive data in the event model. Your custom code must return the same\nevent, after applying any masking.\n\n_For super sensitive data, Moesif recommends leveraging zero-knowledge security with [on-premises client-side encryption](https://www.moesif.com/docs/platform/secure-proxy/) and bring your own keys (BYOK)._\n\n#### getMetadata, (event) =\u003e object, optional\n\nFunction that allow you to append arbitrary JSON metadata to API calls before being logged to Moesif.\n\n#### host, string, optional\n\ndefaults to `api.moesif.net`. If you are using a proxy to send data to Moesif, please set the the host to `proxy.yourcompany.com`.\n\nfull options example:\n\n```javascript\nvar options = {\n  applicationId: \"Your Publishable Moesif Application Id\",\n  skip: function (event) {\n    if (event.request.uri.includes(\"google\")) {\n      return true;\n    }\n    return false;\n  },\n  maskContent: function (event) {\n    if (event.request.headers[\"secret\"]) {\n      event.request.headers[\"secret\"] = \"\";\n    }\n    return event;\n  },\n  getMetadata: function (event) {\n    if (event.request.uri.includes(\"stripe\")) {\n      return {\n        type: \"payment\",\n      };\n    }\n  },\n  host: 'proxy.acmeinc.com'\n};\n\nmoesif.init(options);\n```\n\n#### `requirePublishingConsent`, boolean, optional, default `false`\n\nWhen set to `true`, the SDK will queue all tracking events locally instead of sending them to Moesif. Events remain queued until `grantPublishingConsent()` is called.\n\n```javascript\nmoesif.init({\n  applicationId: 'Your Publishable Moesif Application Id',\n  requirePublishingConsent: true, // Queue events locally until consent is granted\n  maxQueueSize: 1000 // Optional: Set queue size limit\n});\n```\n\n#### `maxQueueSize`, number, optional, default `1000`\n\nThe maximum number of events that can be queued locally before consent is granted. When the queue reaches this limit:\n- The oldest event is dropped (FIFO queue)\n- The newest event is added to the queue\n\nThis prevents unbounded memory growth if a user never grants consent.\n\n```javascript\nmoesif.init({\n  applicationId: 'Your Publishable Moesif Application Id',\n  requirePublishingConsent: true,\n  maxQueueSize: 500 // Limit queue to 500 events\n});\n```\n\n## Ethereum DApp support\n\nDApps (Decentralized Apps) are frontend apps which interact with blockchains such as Ethereum over an API like any other Single Page App. For Ethereum, this API layer uses JSON-RPC and is called the [Ethereum Web3 API](https://github.com/ethereum/web3.js) which Moesif supports natively.\n\nMoesif will capture interactions with the Ethereum blockchain just like any other API to understand usage and monitor for any issues affecting your Dapp. Because this data is binary, there are additional set up steps needed to convert these API interactions into something human readable. [Checkout Moesif's Ethereum Web3 documentation for more info](https://www.moesif.com/docs/platform/ethereum-web3/).\n\nThere is also a tutorial available on [Building an Ethereum DApp with Integrated Web3 Monitoring](https://www.moesif.com/blog/blockchain/ethereum/Tutorial-for-building-Ethereum-Dapp-with-Integrated-Error-Monitoring/).\n\n### Web3 object\n\nMany Dapp clients such as the [Metamask](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en) extension and [Mist Browser](https://github.com/ethereum/mist), will inject a `web3` object directly in the browser's global scope.\n\nThe default `moesif-browser-js` config will automatically instrument the injected web3 object and capture outgoing API transactions to the Ethereum network.\n\nFor advanced scenarios where your code uses a different `web3` object than the default one, you can call `moesif.useWeb3(myWeb3)` to ensure the correct web3 instance is instrumented.\n\nThe web3 object can change if you let users modify the selected web3 provider or change their network. An example is below:\n\n```javascript\nif (typeof web3 !== \"undefined\") {\n  myWeb3 = new Web3(web3.currentProvider);\n  // No action needed by Moesif\n} else {\n  // set the custom provider you want from Web3.providers\n  myWeb3 = new Web3(new Web3.providers.HttpProvider(\"http://localhost:8545\"));\n\n  moesif.useWeb3(myWeb3);\n}\n```\n\n## Troubleshooting\n\n### Response not being logged\nCertain frameworks like Angular monkey patch the XMLHttpRequest heavily. In these cases, enable the eagerBodyLogging option to eagerly capture the response info.\n\n### Incorrect user tracking\n\nIf you see inaccuracies with your customer funnel such as user actions being associated to the wrong user, ensure you are calling `moesif.reset()` when a user logs out of your application. Without this step, Moesif has no knowledge that the user logged out and will continue to associate activity to the old user even if a new user logs into the same device/browser.\n\n### Duplicate API events\n\nBy default, `moesif-browser-js` captures both outgoing API calls from `XMLHttpRequest` and the `web3` object.\nThis way you can see both blockchain related transactions along with other 3rd party APIs like Twilio or Stripe.\n\nIf the Web3 provider is also using the XMLHttpRequest (such as the HttpProvider), it's possible that the same API call is captured twice.\nThis is expected.\n\n`moesif-browser-js` adds metadata depending on the captured source. For events that are captured via `web3`, we add additional [event metadata](https://www.moesif.com/docs/getting-started/api-events/#custom-metadata) for the web3 provider used.\n\nAs an example:\n\n```json\n{\n  \"_web3\": {\n    \"via_web3_provider\": true,\n    \"is_metamask\": true\n  }\n}\n```\n\n### Cross-domain tracking not working\n\n- Confirm `enableCrossDomainTracking: true` is set in `moesif.init()` on **both** the origin and destination domains.\n- Confirm `crossDomainTargets` is explicitly set to `null` (all domains) or an array containing the destination domain. If the option is omitted, no URL decoration will occur.\n- For JS-based navigations (`window.location.href`, `window.open()`, etc.), ensure you are wrapping the target URL with `moesif.cdtUrlDecorator()` before navigating. These methods cannot be intercepted automatically.\n- POST form submissions are not decorated. Use a GET form or a JS-based redirect with `cdtUrlDecorator()` instead.\n- Check whether a privacy-focused browser extension is stripping the `__mt` query parameter. You can customise the parameter name via `crossDomainTrackingParameterName` to avoid conflicts with known filter lists.\n\n## Examples\n\n- Several examples for how to import this library are in the example folder of this repo, _moesif-min_ folder have more examples usage.\n- Example setup for [react-boilerplate](https://github.com/Moesif/moesif-react-boilerplate-example). For React apps, if you set up server-side rendering, please ensure that this library is only initiated on the client-side.\n- Example setup for an [Etherum Dapp](https://github.com/Moesif/moesif-ethereum-js-example).\n\n## Credits for moesif-browser-js\n\nSome of the build scripts, utilities, and directory structure is based on Mixpanel's Javascript Client Library,\nwhich is under Apache 2.0 license.\n\nSome utilities are based on underscore.\n\nTo modify and build this library, please see instructions in Build.md\n\nNote, this library has ZERO external dependencies (only have dev dependencies or dependencies for some of the examples).\n\n## Other integrations\n\nTo view more more documentation on integration options, please visit **[the Integration Options Documentation](https://www.moesif.com/docs/getting-started/integration-options/).**\n\n[ico-built-for]: https://img.shields.io/badge/built%20for-javascript-blue.svg\n[ico-downloads]: https://img.shields.io/npm/dt/moesif-browser-js.svg\n[ico-license]: https://img.shields.io/badge/License-Apache%202.0-green.svg\n[ico-source]: https://img.shields.io/github/last-commit/moesif/moesif-browser-js.svg?style=social\n[link-built-for]: https://developer.mozilla.org/en-US/docs/Web/JavaScript\n[link-downloads]: https://www.npmjs.com/package/moesif-browser-js\n[link-license]: https://raw.githubusercontent.com/Moesif/moesif-browser-js/master/LICENSE\n[link-source]: https://github.com/moesif/moesif-browser-js\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoesif%2Fmoesif-browser-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoesif%2Fmoesif-browser-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoesif%2Fmoesif-browser-js/lists"}