{"_id":"@mostly-good-metrics/javascript","_rev":"19-490d29ec059604439a9343f0dd0011c9","name":"@mostly-good-metrics/javascript","dist-tags":{"latest":"0.13.1"},"versions":{"0.1.0":{"name":"@mostly-good-metrics/javascript","version":"0.1.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.1.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"dde3bde28c9d7d97109830d9c2df72b6ce0c0876","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.1.0.tgz","fileCount":54,"integrity":"sha512-VeClw1OIPnTz2COjo/rN2QESaDoez9dFP3fsSjNqzos032Se1Y/mLAAFEUDobDwF7US9P9mabvtcOVRzTw7XXw==","signatures":[{"sig":"MEUCIQCZTZeurdSPDZwPruYmOIwBc2GdjBN3daUqHR2BstGVOAIgNb23Rz87MwdZLzhrNKgjI3Odg9T/zynwul4LOGhnchQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":254281},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"1e5f007b50bfa2aa846c70b93186fc29f2315b0f","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"joshdholtz","email":"me@joshholtz.com"},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"10.9.4","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"22.21.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.1.0_1765222614444_0.7887610153627043","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@mostly-good-metrics/javascript","version":"0.2.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.2.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"c216625795210a15995ddb5614e66230e06978e0","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.2.0.tgz","fileCount":54,"integrity":"sha512-qTwddqcnu4sU0QGhwU4mHemck5okfh3ExQVUbpQQyVrUyZzOhT2dg3h7AyBgVfIxDwBDXtWgiKqAqhGS+szUaQ==","signatures":[{"sig":"MEQCIBECPyWp6Dh21jPnfOH2/tgYcQB3AqomXw0FOGgW/mCHAiAn3mM2883G3fiaa9HShwXkZpGuVo6xc3cq3srROhKdPg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":257556},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"623c13b0d777f9abf8af1907fb818d0469674378","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"joshdholtz","email":"me@joshholtz.com"},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"8.11.0","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"16.16.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.2.0_1765250029459_0.7683953217721753","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@mostly-good-metrics/javascript","version":"0.4.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.4.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"2026370bdee7dc438c49d694ec3f6099c953a534","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.4.0.tgz","fileCount":54,"integrity":"sha512-Tu9giEVHET00w2UrI2NWMaX2xnGyne0/Uxvg3bb8yEdLYcYObG45HSrmafE0ufGkHduCD+5bpzrCxtjt8s9vtA==","signatures":[{"sig":"MEQCIDi3XL7rXdCR7HB2ZaTOBo82H2wEBYNGg+6WGS5bnyE+AiBZa/qcPTiMQYTSlpbpfhHap3dhopWJgNR2OL4Tu3j/FA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":290599},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"528d27907efdd6c548768d3633955df423c48d6e","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.4.0_1765903438226_0.9642007139807096","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@mostly-good-metrics/javascript","version":"0.4.1","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.4.1","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"89b4c8428abe1a6a5a2989e4f1a1a6ace223652b","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.4.1.tgz","fileCount":55,"integrity":"sha512-T+4djgUCLNqGv5aLROthHnOiS55o8zj0JU/U83rZHUE9YUgb3YtGGDkTvc26WXTdxdFo++bBrOcutb3F1cJ/ag==","signatures":[{"sig":"MEUCIQDSPIplnHVLD7pWUZXI1GUiTwewHhQfPOpOE6W6Dj2RjwIgKFP584xf+VTsK4hA5lm/uTCS0CUl9B5VxFDf16nCFGU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":301662},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"116f9061c6f015b6b61ae1374d2ec9282cf9a327","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.4.1_1765942046566_0.8697385386860839","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"@mostly-good-metrics/javascript","version":"0.4.2","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.4.2","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"fd48623c6b646ff44119551c2eefb1300c03cde4","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.4.2.tgz","fileCount":55,"integrity":"sha512-SZ/mZbSMmTYY07QzgOvCxg6hgVFI2adWo/7pKHN/mmnGLbba9nHZ/cl/JhWtfW0bUioMV8G22icygt32uxQUaw==","signatures":[{"sig":"MEQCIH+3XMZtB6j1bB+5VYvME1erbUhnUSxgqzH7V/XG+pINAiAlLu1iEtgxlUwo8USMFUUUKglLP5JD6ZnXWNHg44hSVg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.4.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":302860},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"cdce02727ca1b25b2683304e5d2d67237b8cee35","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.4.2_1765997276917_0.3436358299276103","host":"s3://npm-registry-packages-npm-production"}},"0.4.3":{"name":"@mostly-good-metrics/javascript","version":"0.4.3","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.4.3","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"10178d1f435fd5653ad26e886c7a9d54a7b166c0","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.4.3.tgz","fileCount":55,"integrity":"sha512-8HwqlYmXJAbtxyNEnHWb6RtvGt/jP5JqdargWPBZhTXj1EeU1kE08GpX5jf/UCiM5R2lqtDl/+QwAIAIqo1hog==","signatures":[{"sig":"MEUCIEFOrtyrpjHa/YilFYN6BMeEoVhtbHpwN6degXEc3YlGAiEAgLEWfufKf8aaUflsir+yhWJxOj1OfngXk1c4IhK6XSI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.4.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":302902},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"d83f640a01e0042ca9befe9c9f08f9f2ac83954d","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.4.3_1766282137577_0.6148323815522709","host":"s3://npm-registry-packages-npm-production"}},"0.4.4":{"name":"@mostly-good-metrics/javascript","version":"0.4.4","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.4.4","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"9ff0a779d40805f41d1a437b01c331f53c94cade","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.4.4.tgz","fileCount":55,"integrity":"sha512-mymEhK5dcyusSCM+w2woLTpm4f18Z9iudTRggX2ntcjS+eOXLIJZzXth/Wy7zv/VNDzqKLbfXVTgJBN3X+ZkmQ==","signatures":[{"sig":"MEUCIQDduG9GYdPSompSyepYLz38Cg7lKg2ewkZUEhqz/N8VdwIgCAmRuq7sPfYRmJ9UskdQPRAA8oyRsXJxPGw4hsi969Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.4.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":307490},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"ae2839c676265ad699ffb46604a3e8649877ca6f","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.4.4_1766416332402_0.790227306723456","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@mostly-good-metrics/javascript","version":"0.5.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.5.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"9061cf0209512d8bdfda74d9ba246af88874523f","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.5.0.tgz","fileCount":55,"integrity":"sha512-kweO7P/jiU5Vetk0iDmXpV9M70CrZHlRQ/MKTFqVPUCYWa6z27MchqF/8H1MEHQ5vbHg27CJpMyNj0jgL0gYFg==","signatures":[{"sig":"MEUCIQDhCiyAfWctx6SGxvdYuOJREHrFBy5NIEwA36szixmofAIgOoQLIuEssEmOnQClGX9tkm/f5t2blmfayYL10/dBKME=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":347465},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"79cbea1e159b1d2cbd2047e18495d038d259941a","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.5.0_1766810981873_0.6996219081437105","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"@mostly-good-metrics/javascript","version":"0.5.1","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.5.1","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"732a412e93afba5d2aa5e9423f6747ca62e17db3","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.5.1.tgz","fileCount":55,"integrity":"sha512-ai50rD0TSkne2RPR3S+lO2WsJqg3DxsXt1mvS31HlnLwYZoLwdRHgeTY7oJnF2gz4vES69mu4WYWC0ZAbEyZuA==","signatures":[{"sig":"MEUCIQDR96qsAHQq2At+aELD4iZ+LOObcHbopB8QeWSR6KliXwIgbtD3mmG4x1AFHlxurs/ZhfWyTKgx3d7N6/Z1e3KkX6k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.5.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":372551},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"d30ab13c7ba49cd78aca00c460ab83b6ce4c1c59","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.5.1_1767841837116_0.5944849325386803","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@mostly-good-metrics/javascript","version":"0.6.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.6.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"4e3090420f73f5f89178a7a7ca327354c90d648e","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.6.0.tgz","fileCount":55,"integrity":"sha512-NgH6EA5/V8PRy8JFyXDdqwITQcY+Jjd2BSWxIhLApm5lUxam1lyLXXimgcjpzjPRm8pft5r6Txppf9G7qLhdNw==","signatures":[{"sig":"MEQCIBYp9dwtZSXb9qSjFjslaUQVFPaI0QduxKlS+1rS2TDMAiBEt+YKzgzvyQJhhKWgEjlzWqIi48C3TgSsObulkTrg3w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":407520},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"4712b2cbabde704c62b22f5e14f46c8985b40477","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.6.0_1768162285748_0.3128232984503567","host":"s3://npm-registry-packages-npm-production"}},"0.6.1":{"name":"@mostly-good-metrics/javascript","version":"0.6.1","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.6.1","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"07a81ddbd28c7866d1314334fe10f3cf10cd216c","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.6.1.tgz","fileCount":55,"integrity":"sha512-bPdW5j3mb2MqDLicD0wPtpsa66EjxnyAeF6yum7zwjcw5mlSXwoYfZW7teyD7JR++LRK0U5UMORDKtfKz299Ww==","signatures":[{"sig":"MEQCIHfc2icb+12oGc6Hk8y5lbJeLf3WGsFZe76dFlo49NxmAiAf35U9dIB5/JnZJg1jc2NoCIVjwSmDlerly9GTqqpuGw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.6.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":407845},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"c6f2a5f89b8d799e4ec9db603d5316e950022c37","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.6.1_1768188035417_0.19155906856840255","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@mostly-good-metrics/javascript","version":"0.7.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.7.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"1f46f9271b3cff40840d80c54ea89923d7234f9b","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.7.0.tgz","fileCount":55,"integrity":"sha512-hVMluo9PMDE45MBtptpdCtKz8OI2ZJWToI/pZ0wlVEsHc5hkr6r8O16hV6y1aCmR2mze9saEUbDX0dOtWLWZGA==","signatures":[{"sig":"MEUCIQD7Luv5fwb8dTkDlr/7+/rBgEu/CbIvfZne/OCOpPVHkwIgB01/CrG5LkbyHLSWZJ+9ZmSOvt3P8es8fuUkjhgXdTY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.7.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":425766},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"2dc889218317930d41ffc635f4e18bbf4a326916","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.7.0_1768867296697_0.8118115898566445","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"@mostly-good-metrics/javascript","version":"0.8.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.8.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"d20a4fc4951dabb08c7b4cc102a74f9cdcb7d426","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.8.0.tgz","fileCount":56,"integrity":"sha512-quaruQmkgzMRRTL7hJ4V59mbpfE0gKocZNzJWFJZbdkNrv4cpJXsN06VR1Rxq+43kU6jnZG++WyHcD8JPnw/ug==","signatures":[{"sig":"MEUCIQDAVPCTksYawcAsy1qYaS9/NQUUNCeD14LTSCxt+RMHWgIgIcr/6V2gjABl4y5tlAocwDfZrm00VsRDujeHTiEKsCU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.8.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":491742},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"451b7444d554749577dbbe851714f77f936d3b6a","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.16.0","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.18.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.8.0_1784041204474_0.5585652970902535","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"@mostly-good-metrics/javascript","version":"0.9.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.9.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"906b8210dab3aa3fdf12310ce43153a67a2ea1ba","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.9.0.tgz","fileCount":64,"integrity":"sha512-ok0bpzBG2lPCWKKPxsFkfEtojJE5FMUyNaE5712POyrAlN5TnSM/+VoNZWGvgNPxObvGEWJlwLQV/Cvf5aQgUg==","signatures":[{"sig":"MEUCIQC+ZXwueGCYfYsnHJ1B/Ekx1QenQT2AEsWUCI9af/3y+AIgXZNwKdKZjB49TIrRh+ZzPxhyY+rkapNUzUahRp7w9go=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.9.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":685835},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"c6315e9bf211fd66c790068e24c4ec8d79f19c80","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.16.0","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.18.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.9.0_1785811505115_0.3270224870478491","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"@mostly-good-metrics/javascript","version":"0.10.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.10.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"cad8030a6c48dd46c1e6e863d602de8445fd23a2","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.10.0.tgz","fileCount":64,"integrity":"sha512-PVdeBp9ev59+fnQjvHzfZmFSrFZd+Eo7NYc+/Kv1ppRUb2dyFAq6vyWJiILFyVLvxMn6/N+Z77P/9OeyxsivDQ==","signatures":[{"sig":"MEYCIQC/soidYDsVnD2AMCpfC4Qo//2XfP53/TqfZArC2AFaKQIhAMrWhhO844k4RmhC+vcvOVfiswdE9vSht7L3GFXrnh9t","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.10.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":689283},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"97af460a242768112b64ffd5e4cc1da55f617c07","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.17.0","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.10.0_1787003490908_0.29717731685635207","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"name":"@mostly-good-metrics/javascript","version":"0.11.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.11.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"4ace7164730be2fae86a3966cc6cdf32b94e1669","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.11.0.tgz","fileCount":64,"integrity":"sha512-Msa8AcZYMpH2EwDCMzRrLTjf7HUouRbipGc2RbdQT/mJStvOTlRoDNAGDVeQdCxTkoG8Vaf9osEnfLvs0hciTw==","signatures":[{"sig":"MEYCIQCQyRrT5DX4Hihw44ClLStvfXIG3QTis98Eq8Hym26KdgIhAIbW4tuF9G0mw5gda/OZfbkBvVXoCh866i7OkTD7jbWQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.11.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":703128},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"3ae4da66ee79589362554c44304d259d7a942bb4","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.17.0","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.11.0_1788049067454_0.27142017881175007","host":"s3://npm-registry-packages-npm-production"}},"0.12.0":{"name":"@mostly-good-metrics/javascript","version":"0.12.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.12.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"f80789ddb5752776c6bc3144b8da8c17d78a30a3","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.12.0.tgz","fileCount":64,"integrity":"sha512-KGxq+yPuUeOlqYyud82jEL/O4WRz0Q7dSwjfj1f4F/ArBoNouRV3d4pLQjTuXMFYaLQ2AhQTHyumrE+1xIrqbA==","signatures":[{"sig":"MEQCIF+KFYPwJMAJVvP3FSG0xzeZQJ1Tx7eI1LFl7S7xgA4CAiByjlk2u+H86ydC0lQPKTGfBTpL4nvtIwVcFcrBCNjptg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIAW21ltyb5boesf9tf9i9ptD4c/CcU7ujNK0AVrRFSxSAiB+On5va8+WjsndoSBeAdE+EFbHsbQ5rMYf1WGYpGephA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.12.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":769480},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"2d72f81c3b0e5326e2704c60e1388ac3296f8f9e","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.19.0","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.12.0_1788656045181_0.0896669955791185","host":"s3://npm-registry-packages-npm-production"}},"0.13.0":{"name":"@mostly-good-metrics/javascript","version":"0.13.0","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"author":"","license":"MIT","_id":"@mostly-good-metrics/javascript@0.13.0","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"homepage":"https://mostlygoodmetrics.com","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"e44cdc94df72e66cc6dcf7f81b85b421f587dbf4","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.13.0.tgz","fileCount":64,"integrity":"sha512-AvlSDyNXa950Fa79eISPvIxKVE13hW8u6lxmILBTU41PZZAFUDWgvAImneTG2qliz0+HB3tFyBNYTdUJwaNzHA==","signatures":[{"sig":"MEUCIFX3lxJ6DzG9WwJ+aCvZ7RHaLZnSTB/RmQxXfSEvuFHaAiEAu7PmbIFvYls9k4GmeKQRQE2CRPw2N62qJgTTnlrwlUo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDm5UmAPelSNlVDKRn/rxKrX7Wbncu6dyMXwxX4B1zn0AIhAOIwRnXQDrJXjqhNVDsDL+RY7TFVAp+gKuV1a13fii4P","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.13.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":802520},"main":"dist/cjs/index.js","types":"dist/types/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"77164ad4be420df819d9206e1e1965ddb0b52a48","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build","test:browser-storage":"node scripts/browser-storage.test.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.19.0","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"_nodeVersion":"24.21.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","esbuild":"^0.25.12","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","playwright-core":"^1.55.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/javascript_0.13.0_1790431704474_0.040408915610401275","host":"s3://npm-registry-packages-npm-production"}},"0.13.1":{"_id":"@mostly-good-metrics/javascript@0.13.1","bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"dist":{"shasum":"ba6828e688f84de19abd56139367139facaead1b","tarball":"https://registry.npmjs.org/@mostly-good-metrics/javascript/-/javascript-0.13.1.tgz","fileCount":66,"integrity":"sha512-deO0ujmVMcKxFsvs0pX8lvvXtYhunKr3ni7nEs4CIgGDHfOlr/e6P2q924nsfcVxAIZHiTQGQZhFEE+8PJkpNA==","signatures":[{"sig":"MEUCIB+y1Bzvz7QvBRNiRPQsYTKx6N0DWqlmsze3rmqhER+kAiEAuIK3/juG3q/OGfr/DubMhvrajfyAUms/65d10YxwdYA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD70LVGmVANw+3uNvkZgxlMPaypDwgwqEbxx2yJQqCR1gIhAJIgu1avwrTlNciPI+xAyEBn7wL1ZigksQ0KmzFpe8Jz"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@mostly-good-metrics%2fjavascript@0.13.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":949341},"main":"dist/cjs/index.js","name":"@mostly-good-metrics/javascript","types":"dist/types/index.d.ts","author":"","module":"dist/esm/index.js","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"0e8f30966a78a2862306a6c190a166e355e84298","license":"MIT","scripts":{"lint":"eslint src --ext .ts","test":"jest","build":"npm run build:cjs && npm run build:esm && npm run build:types","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint src --ext .ts --fix","build:cjs":"tsc -p tsconfig.cjs.json","build:esm":"tsc -p tsconfig.esm.json","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:types":"tsc -p tsconfig.types.json","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run clean && npm run build","test:browser-storage":"node scripts/browser-storage.test.mjs"},"version":"0.13.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"4d5f17e6-0fad-4785-aa55-f70a7e4c4383"}},"homepage":"https://mostlygoodmetrics.com","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"_npmVersion":"11.19.0","description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","directories":{},"maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"_nodeVersion":"24.21.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","esbuild":"^0.25.12","ts-jest":"^29.1.2","prettier":"^3.2.0","typescript":"^5.3.0","@types/jest":"^29.5.12","@types/node":"^20.11.0","playwright-core":"^1.55.0","eslint-config-prettier":"^9.1.0","jest-environment-jsdom":"^29.7.0","@typescript-eslint/parser":"^7.0.0","@typescript-eslint/eslint-plugin":"^7.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/javascript_0.13.1_1790976200694_0.6965497000744107"}}},"time":{"created":"2025-12-08T19:36:54.358Z","modified":"2026-10-02T21:23:21.192Z","0.1.0":"2025-12-08T19:36:54.620Z","0.2.0":"2025-12-09T03:13:49.602Z","0.4.0":"2025-12-16T16:43:58.396Z","0.4.1":"2025-12-17T03:27:26.750Z","0.4.2":"2025-12-17T18:47:57.090Z","0.4.3":"2025-12-21T01:55:37.718Z","0.4.4":"2025-12-22T15:12:12.550Z","0.5.0":"2025-12-27T04:49:42.025Z","0.5.1":"2026-01-08T03:10:37.280Z","0.6.0":"2026-01-11T20:11:25.913Z","0.6.1":"2026-01-12T03:20:35.560Z","0.7.0":"2026-01-20T00:01:36.915Z","0.8.0":"2026-07-14T15:00:04.603Z","0.9.0":"2026-08-04T02:45:05.273Z","0.10.0":"2026-08-17T21:51:31.052Z","0.11.0":"2026-08-30T00:17:47.609Z","0.12.0":"2026-09-06T00:54:05.277Z","0.13.0":"2026-09-26T14:08:24.574Z","0.13.1":"2026-10-02T21:23:20.805Z"},"bugs":{"url":"https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js/issues"},"license":"MIT","homepage":"https://mostlygoodmetrics.com","keywords":["analytics","metrics","tracking","events","mostlygoodmetrics"],"repository":{"url":"git+https://github.com/Mostly-Good-Metrics/mostly-good-metrics-js.git","type":"git"},"description":"JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications","maintainers":[{"name":"joshdholtz","email":"me@joshholtz.com"}],"readme":"# MostlyGoodMetrics JavaScript SDK\n\nA lightweight JavaScript/TypeScript SDK for tracking analytics events with [MostlyGoodMetrics](https://mostlygoodmetrics.com).\n\n## Table of Contents\n\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [User Identification](#user-identification)\n- [Privacy](#privacy)\n- [Configuration Options](#configuration-options)\n- [Migrating an Existing Site](#migrating-an-existing-site)\n- [Automatic Events](#automatic-events)\n- [Automatic Properties](#automatic-properties)\n- [Automatic Context](#automatic-context)\n- [Event Naming](#event-naming)\n- [Properties](#properties)\n- [Manual Flush](#manual-flush)\n- [A/B Testing (Experiments)](#ab-testing-experiments)\n- [Local Experiment Enrollment](#local-experiment-enrollment)\n- [Automatic Behavior](#automatic-behavior)\n- [Debug Logging](#debug-logging)\n- [Framework Integration](#framework-integration)\n- [Custom Storage](#custom-storage)\n- [License](#license)\n\n## Requirements\n\n- Node.js 18+ (for build tools)\n- Modern browser with ES2020 support, or Node.js runtime\n\n## Installation\n\n```bash\nnpm install @mostly-good-metrics/javascript\n```\n\nOr with yarn:\n\n```bash\nyarn add @mostly-good-metrics/javascript\n```\n\n## Quick Start\n\n### 1. Initialize the SDK\n\nInitialize once at app startup:\n\n```typescript\nimport { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';\n\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n});\n```\n\n### 2. Track Events\n\n```typescript\n// Simple event\nMostlyGoodMetrics.track('button_clicked');\n\n// Event with properties\nMostlyGoodMetrics.track('purchase_completed', {\n  product_id: 'SKU123',\n  price: 29.99,\n  currency: 'USD',\n});\n```\n\n### 3. Identify Users\n\n```typescript\n// Set user identity (optional - anonymous ID is auto-generated)\nMostlyGoodMetrics.identify('user_123');\n\n// Reset identity (e.g., on logout)\nMostlyGoodMetrics.resetIdentity();\n```\n\nThat's it! Events are automatically batched and sent.\n\n## User Identification\n\nThe SDK automatically generates and persists an anonymous user ID (UUID) for each user. This anonymous ID is stored in both cookies and localStorage, persisting across sessions.\n\n```typescript\n// Before identify(): user_id = auto-generated UUID (e.g., \"550e8400-e29b-41d4-a716-446655440000\")\nMostlyGoodMetrics.identify('user_123');\n// After identify(): user_id = \"user_123\"\n\nMostlyGoodMetrics.resetIdentity();\n// After reset: user_id = new auto-generated UUID\n```\n\nWhen `identify()` sends a `$identify` event (i.e. when you pass profile data such as `email` or `name`), the event's `properties` include `$anonymous_id` set to the anonymous ID the user had before `identify()` was called. Its `user_id` is the newly-identified ID. This lets the backend link a user's earlier anonymous events to their identified ID. `$anonymous_id` is omitted when there is no distinct anonymous ID (e.g. the anonymous ID already equals the identified ID).\n\n### Cross-Subdomain Tracking\n\nTo track users across subdomains (e.g., `app.example.com` and `blog.example.com`), configure a shared cookie domain:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  cookieDomain: '.example.com', // Share ID across all *.example.com subdomains\n});\n```\n\n### Privacy Mode\n\nFor privacy-focused implementations or GDPR compliance, you can disable cookies entirely:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  disableCookies: true, // Uses localStorage only, no cookies\n});\n```\n\nWhen `disableCookies: true`:\n- Anonymous ID stored in localStorage only\n- No cookies are set\n- Cross-subdomain tracking is disabled\n\nSee the [Privacy](#privacy) section for the full set of privacy controls (opt-out, Do Not Track, memory-only persistence, forget-me, and more).\n\n## Privacy\n\nThe SDK ships with a full set of privacy controls: user-level opt-out, browser privacy signals (Do Not Track / Global Privacy Control), anonymous ID rotation and a full \"forget me\", reduced data collection, and configurable persistence including a memory-only mode.\n\n### Opt-out / opt-in\n\n```typescript\nMostlyGoodMetrics.optOut();      // Stop all tracking immediately\nMostlyGoodMetrics.isOptedOut();  // => true\nMostlyGoodMetrics.optIn();       // Resume tracking\n```\n\n- `optOut()` immediately stops tracking: `track()`, `identify()` and `flush()` become no-ops, and no network requests (including experiment and local-experiment-config fetches) are made. In local enrollment mode, `getVariant()` still buckets from inline or cached configs, but no `$experiment_exposure` events (or their dedup state) are recorded until `optIn()`.\n- Any queued (unsent) events are purged on opt-out, so nothing tracked before the call is ever sent.\n- The choice is persisted (localStorage + cookie, consistent with the anonymous ID) and survives page reloads. In `persistence: 'memory'` mode nothing is written, so the choice only lasts for the page session.\n- An explicit `optIn()` is also persisted and overrides `optedOutByDefault` and Do Not Track defaults on later visits.\n\n### Consent-first sites (`optedOutByDefault`)\n\nFor sites that must not track before consent, start opted out and opt the user in once they consent:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  optedOutByDefault: true,\n  persistence: 'memory', // optional: also avoid writing any IDs before consent\n});\n\n// Later, when the user consents:\nMostlyGoodMetrics.optIn();\n```\n\nA previously persisted `optIn()`/`optOut()` choice takes precedence over `optedOutByDefault`.\n\n> **Tip:** `optedOutByDefault` alone still persists an anonymous ID to localStorage/cookies. Combine it with `persistence: 'memory'` if nothing may be written before consent, then call `optIn()` after consent (note: with memory persistence the anonymous ID resets on every page load).\n\n### Do Not Track / Global Privacy Control (`respectDoNotTrack`)\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  respectDoNotTrack: true,\n});\n```\n\nWhen enabled, the SDK treats `navigator.doNotTrack === '1'` or `navigator.globalPrivacyControl === true` as opted out from initialization. Off by default. An explicit persisted `optIn()` takes precedence over the browser signal.\n\n### Resetting the anonymous ID / forget me\n\n```typescript\n// Rotate just the anonymous ID (returns the new ID)\nMostlyGoodMetrics.resetAnonymousId();\n\n// Standard logout: clear the user ID, keep the anonymous ID\nMostlyGoodMetrics.resetIdentity();\n\n// Full \"forget me\": also rotates the anonymous ID and purges local state\nMostlyGoodMetrics.resetIdentity({ clearAnonymousId: true });\n```\n\n`resetIdentity({ clearAnonymousId: true })` clears everything tied to the previous identity:\n\n- User ID and identify debounce state\n- Anonymous ID (rotated to a fresh one)\n- Queued (unsent) events\n- Super properties (including `$experiment_*` assignments)\n- Cached experiment variants and exposure dedup flags\n- Sticky local experiment assignments (local enrollment mode), so the new anonymous ID is re-bucketed - `resetAnonymousId()` clears these too\n\n### Reduced data collection (`collectDeviceProperties`)\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  collectDeviceProperties: false,\n});\n```\n\nWhen `false`, the SDK omits `$device_type` and `$device_model` from event properties and `locale`/`timezone` from events and batch context. `platform`, `os_version` and `app_version` are still sent. Default: `true`.\n\n### Persistence modes (`persistence`)\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  persistence: 'memory', // 'localStorage+cookie' (default) | 'localStorage' | 'memory'\n});\n```\n\n| Mode | Anonymous ID | Event queue | Cookies | Survives reload |\n|------|--------------|-------------|---------|-----------------|\n| `'localStorage+cookie'` (default) | localStorage + cookie | localStorage | Yes (enables cross-subdomain tracking) | Yes |\n| `'localStorage'` | localStorage only | localStorage | No | Yes |\n| `'memory'` | In-memory only | In-memory only | No | No |\n\nIn `'memory'` mode nothing is written to localStorage or cookies: the anonymous ID, event queue, super properties, opt-out flag and experiment cache all live in memory and are lost on reload. `disableCookies: true` keeps working as an alias for `persistence: 'localStorage'`; an explicit `persistence` option wins over `disableCookies`.\n\n### What the SDK collects automatically\n\nWith default settings, every event includes:\n\n- **Identity**: `user_id` (identified ID or generated anonymous ID), `session_id` (per page load)\n- **Device** (disable with `collectDeviceProperties: false`): `$device_type`, `$device_model`, `locale`, `timezone`\n- **App/environment**: `platform`, `os_version`, `app_version` (if configured), `environment`, `$sdk`\n- **Metadata**: `client_event_id`, `timestamp`\n\nSee [Automatic Properties](#automatic-properties) and [Automatic Context](#automatic-context) for the full reference. The SDK never reads or transmits anything beyond what is listed there plus the properties you pass explicitly.\n\n## Configuration Options\n\nFor more control, pass additional configuration:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  baseURL: 'https://ingest.mostlygoodmetrics.com',\n  environment: 'production',\n  appVersion: '1.0.0',\n  maxBatchSize: 100,\n  flushInterval: 30,\n  maxStoredEvents: 10000,\n  enableDebugLogging: process.env.NODE_ENV === 'development',\n  trackAppLifecycleEvents: true,\n  trackPageViews: true,\n  cookieDomain: '.yourdomain.com',\n  disableCookies: false,\n});\n```\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `apiKey` | - | **Required.** Your API key |\n| `baseURL` | `https://ingest.mostlygoodmetrics.com` | API endpoint |\n| `environment` | `\"production\"` | Environment name |\n| `appVersion` | - | App version string (required for install/update tracking) |\n| `maxBatchSize` | `100` | Events per batch (1-1000) |\n| `flushInterval` | `30` | Auto-flush interval in seconds |\n| `maxStoredEvents` | `10000` | Max cached events |\n| `enableDebugLogging` | `false` | Enable console output |\n| `trackAppLifecycleEvents` | `false` | Auto-track lifecycle events ($app_opened, etc.) |\n| `trackPageViews` | `false` | Capture page views, SPA navigation, and active page engagement for Web Analytics |\n| `sessionTimeoutMinutes` | `30` | Start a new web session after this many inactive minutes |\n| `existingInstallation` | `false` | Establish lifecycle state without a migration-time `$app_installed` |\n| `contextProvider` | - | Dynamic properties evaluated when each event is captured |\n| `bundleId` | auto-detected | Custom bundle identifier |\n| `cookieDomain` | - | Cookie domain for cross-subdomain tracking (e.g., `.example.com`) |\n| `disableCookies` | `false` | Disable cookies entirely (alias for `persistence: 'localStorage'`) |\n| `persistence` | `'localStorage+cookie'` | Where SDK state lives: `'localStorage+cookie'`, `'localStorage'`, or `'memory'` (see [Privacy](#privacy)) |\n| `optedOutByDefault` | `false` | Start opted out until `optIn()` is called (consent-first sites) |\n| `respectDoNotTrack` | `false` | Honor `navigator.doNotTrack` / Global Privacy Control as opt-out |\n| `collectDeviceProperties` | `true` | Collect `$device_type`, `$device_model`, `locale`, `timezone` |\n| `anonymousId` | auto-generated | Override anonymous ID (for wrapper SDKs) |\n| `storage` | auto-detected | Custom storage adapter (see [Custom Storage](#custom-storage)) |\n\n| `networkClient` | fetch-based | Custom network client |\n| `experimentStorage` | auto-detected | Custom key-value storage for the experiments cache (see [A/B Testing](#ab-testing-experiments)) |\n| `experimentMode` | `'server'` | `'server'` (server-assigned variants) or `'local'` (on-device bucketing, see [Local Experiment Enrollment](#local-experiment-enrollment)) |\n| `localExperiments` | - | Inline experiment configs for local mode (zero network) |\n\n## Migrating an Existing Site\n\nWhen adding MGM to an already-deployed site, set `existingInstallation` from a\nlegacy marker that proves this browser/device existed before MGM. MGM records\nthe current `appVersion` as its lifecycle baseline without treating those users\nas fresh installs:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  appVersion: '2.0.0',\n  trackAppLifecycleEvents: true,\n  existingInstallation: legacyAnalytics.hasInstallationMarker(),\n});\n```\n\nFuture version changes still emit `$app_updated`. Do not set this to `true` for\nevery visitor: doing so would suppress `$app_installed` for genuine new users.\n\n## Automatic Events\n\nFor website analytics, opt in once during configuration:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  trackPageViews: true,\n});\n```\n\nPage views and visible-page engagement are stored in the SDK's durable browser\nqueue before delivery. When a page is hidden or closed, MGM also starts a\nbyte-bounded `fetch` keepalive request. Browsers treat teardown delivery as\nbest-effort; anything they do not send remains queued for the next visit.\n\nThis captures an initial `page_view`, subsequent `pushState`, `replaceState`,\nand back/forward navigation, plus `$page_engagement` when the page becomes\nhidden. Page views include `url`, `hostname`, `pathname`, `title`, `referrer`,\n`referring_domain`, and any `utm_source`, `utm_medium`, `utm_campaign`,\n`utm_term`, or `utm_content` values. A session continues across reloads and\nnavigation until 30 minutes of inactivity (configurable with\n`sessionTimeoutMinutes`).\n\nWhen `trackAppLifecycleEvents` is enabled, the SDK automatically tracks:\n\n| Event | When | Properties |\n|-------|------|------------|\n| `$app_installed` | First visit (localStorage) | `$version` |\n| `$app_updated` | Version change detected | `$version`, `$previous_version` |\n| `$app_opened` | Page load / tab visible | - |\n| `$app_backgrounded` | Tab hidden / page unload | - |\n\n> **Note:** Install and update detection require `appVersion` to be configured.\n\n## Automatic Properties\n\nThe SDK automatically includes these properties with every event:\n\n| Property | Description | Example | Source |\n|----------|-------------|---------|--------|\n| `$device_type` | Device form factor | `desktop`, `phone`, `tablet` | Detected from user agent and screen size |\n| `$device_model` | Browser name and major version | `Chrome 120.0` | Parsed from user agent |\n| `$browser` | Browser name | `Chrome`, `Safari`, `Firefox` | Parsed from user agent |\n| `$browser_version` | Full browser version | `120.0.6099.130` | Parsed from user agent |\n| `$os` | Operating system name | `Mac OS X`, `Windows`, `Linux`, `iOS`, `Android` | Parsed from user agent |\n| `$os_version` | Operating system version | `10.15.7` | Parsed from user agent |\n| `$screen_width` | Screen width in pixels | `1920` | `window.screen.width` |\n| `$screen_height` | Screen height in pixels | `1080` | `window.screen.height` |\n| `$viewport_width` | Viewport width in pixels | `1440` | `window.innerWidth` |\n| `$viewport_height` | Viewport height in pixels | `900` | `window.innerHeight` |\n| `$user_agent` | Full user agent string | `Mozilla/5.0...` | `navigator.userAgent` |\n\n> **Note:** Properties with the `$` prefix are reserved for system use. Do not use the `$` prefix for your own custom properties.\n\n## Automatic Context\n\nThe SDK automatically includes these fields with every event to provide rich context:\n\n### Identity & Session\n\n| Field | Description | Example | Persistence |\n|-------|-------------|---------|-------------|\n| `user_id` | Identified user ID (set via `identify()`) or auto-generated anonymous UUID | `user_123` | Persisted in cookies + localStorage (survives page reloads) |\n| `session_id` | UUID generated per page load | `abc123-def456` | Regenerated on each page load |\n\n### Device & Platform\n\n| Field | Description | Example | Source |\n|-------|-------------|---------|--------|\n| `platform` | Platform identifier | `web` | Hardcoded |\n| `locale` | User's locale | `en-US` | `Intl.DateTimeFormat().resolvedOptions().locale` |\n| `timezone` | User's timezone | `America/New_York` | `Intl.DateTimeFormat().resolvedOptions().timeZone` |\n\n### App & Environment\n\n| Field | Description | Example | Source |\n|-------|-------------|---------|--------|\n| `app_version` | App version (if configured) | `1.2.0` | Configuration option |\n| `environment` | Environment name | `production`, `staging`, `development` | Configuration option (default: `production`) |\n\n### Event Metadata\n\n| Field | Description | Example | Purpose |\n|-------|-------------|---------|---------|\n| `client_event_id` | Unique UUID for each event | `550e8400-e29b-41d4-a716-446655440000` | Deduplication (prevents processing the same event twice) |\n| `timestamp` | ISO 8601 timestamp when event was tracked | `2024-01-15T10:30:00.000Z` | Event ordering and time-based analysis |\n\n## Event Naming\n\nEvent names must:\n- Start with a letter (or `$` for system events)\n- Contain only alphanumeric characters and underscores\n- Be 255 characters or less\n\n> **Note:** The `$` prefix is reserved for system events (like `$app_opened`, `$app_installed`). Do not use `$` for custom event names.\n\n```typescript\n// Valid\nMostlyGoodMetrics.track('button_clicked');\nMostlyGoodMetrics.track('PurchaseCompleted');\nMostlyGoodMetrics.track('step_1_completed');\n\n// Invalid (will be ignored)\nMostlyGoodMetrics.track('123_event');      // starts with number\nMostlyGoodMetrics.track('event-name');     // contains hyphen\nMostlyGoodMetrics.track('event name');     // contains space\nMostlyGoodMetrics.track('$custom_event');  // $ prefix is reserved\n```\n\n## Properties\n\nEvents support various property types:\n\n```typescript\nMostlyGoodMetrics.track('checkout', {\n  string_prop: 'value',\n  int_prop: 42,\n  double_prop: 3.14,\n  bool_prop: true,\n  null_prop: null,\n  list_prop: ['a', 'b', 'c'],\n  nested: {\n    key: 'value',\n  },\n});\n```\n\n### Dynamic global properties\n\nUse `contextProvider` for values that can change while a page is open. The\nprovider runs for every event and its result is never persisted:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  contextProvider: () => ({\n    organization_id: currentOrganization.id,\n    subscription_tier: currentUser.plan,\n  }),\n});\n```\n\nThe provider runs synchronously on the JavaScript caller. Return ordinary JSON-like\nvalues; asynchronous providers are unsupported. MGM contains provider exceptions\nand observes rejected callback promises so they do not become unhandled rejections.\nUnreadable property getters are omitted, and property traversal is bounded to\nprevent oversized or recursive arrays from exhausting capture work. Properties\nare copied when captured, including super properties, so later mutation does not\nchange queued events.\n\nCollision precedence is: super properties < dynamic context < event properties\n< MGM system properties. `$`-prefixed keys are MGM-reserved; with\n`enableDebugLogging: true`, MGM warns when custom event/context properties use\nthose keys.\n\n**Limits:**\n- String values: truncated to 1000 characters\n- Nesting depth: max 3 levels\n- Total properties size: max 10KB\n\n## Manual Flush\n\nEvents are automatically flushed periodically and when the page is hidden. You can also trigger a manual flush:\n\n```typescript\nawait MostlyGoodMetrics.flush();\n```\n\nAutomatic timer and page-exit flushes contain storage/network failures and keep\nunsent events queued for retry. Explicitly awaited `flush()`,\n`clearPendingEvents()`, and `getPendingEventCount()` retain their promise failure\nbehavior for custom adapters; handle those promises in your application. SDK\nerror handlers may return a promise; MGM observes its rejection, but does not\nwait for asynchronous error handling before continuing delivery.\n\nBuilt-in event stores also cap queued event JSON at approximately 1 MiB. The SDK\nevicts the oldest events when either this byte ceiling or `maxStoredEvents` is\nreached. An individual event larger than the ceiling is dropped. Oversized\npersisted queues are ignored before parsing so recovery cannot exhaust the host\nheap. Truncated property strings are copied so they cannot retain a much larger\nsource string. Stored super properties, experiment caches and supported streamed\nexperiment responses are also checked before parsing. Older fetch adapters without\nreadable body streams own the allocation needed to produce their text/JSON\nresponses. Custom event storage adapters own their own memory and persistence\nlimits.\n\nTo check pending events:\n\n```typescript\nconst count = await MostlyGoodMetrics.getPendingEventCount();\nconsole.log(`${count} events pending`);\n```\n\n## A/B Testing (Experiments)\n\nVariants are assigned server-side (`GET /v1/experiments`) so the same user always gets the same variant for the same experiment.\n\n```typescript\n// Wait for experiments to load (resolves immediately if cached).\n// Resolves after 5 seconds at the latest so a hanging network never\n// blocks startup - pass a custom timeout with ready(timeoutMs).\n// ready() never rejects; if it times out, getVariant() returns fallbacks\n// until the in-flight fetch completes (a late response is still applied).\nawait MostlyGoodMetrics.ready();\n\n// Get the assigned variant, with an optional fallback for when the\n// experiment is unknown or experiments haven't loaded yet (default: null)\nconst variant = MostlyGoodMetrics.getVariant('checkout-flow', 'control');\n\nif (variant === 'treatment') {\n  // show the new checkout\n}\n```\n\n### Caching (stale-while-revalidate, no TTL)\n\nAssigned variants are cached locally per user and **never expire**:\n\n- Cached variants are served synchronously as soon as they are hydrated; `ready()` resolves without waiting for the network.\n- On a cold cache, `ready(timeoutMs = 5000)` resolves when the first experiments load settles or the timeout elapses, whichever comes first (it never rejects). The underlying request is aborted after 60 seconds so it always settles; a response arriving after a `ready()` timeout is still applied atomically.\n- A background refetch keeps assignments up to date, throttled to at most once per hour (the last-fetch timestamp is persisted).\n- On `identify()` with a changed user ID, the SDK keeps serving the current in-memory variants, refetches immediately (passing `anonymous_id` alongside `user_id` so the server can alias pre-identify assignments), and atomically swaps in the response. Variants are never cleared to null mid-session.\n\n### Exposure tracking\n\nOn the first `getVariant()` hit per (user, experiment, variant), the SDK automatically tracks a `$experiment_exposure` event with properties `$experiment_name` (the raw experiment name) and `$variant`. Deduplication flags are persisted, so exposures are not re-tracked across page reloads or app restarts.\n\nThe variant is also stored as a super property (`$experiment_{name}: variant`, snake_cased) so it is attached to all subsequent events.\n\n### Custom experiment storage (React Native)\n\nThe experiments cache and exposure flags are persisted through a small pluggable key-value interface (`IExperimentStorage`). By default the SDK uses localStorage (or in-memory storage where unavailable). React Native apps should inject AsyncStorage:\n\n```typescript\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { MostlyGoodMetrics, IExperimentStorage } from '@mostly-good-metrics/javascript';\n\nconst experimentStorage: IExperimentStorage = {\n  getItem: (key) => AsyncStorage.getItem(key),\n  setItem: (key, value) => AsyncStorage.setItem(key, value),\n};\n\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  experimentStorage,\n});\n```\n\nAsync adapters are fully supported - cache hydration completes before `ready()` resolves.\n\n## Local Experiment Enrollment\n\nBy default, experiment variants are assigned by the server (`experimentMode: 'server'`), which sends the user ID with the experiments request. If you prefer that **no user identifier ever leaves the device** for experiment enrollment, switch to local mode:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  experimentMode: 'local',\n});\n\nawait MostlyGoodMetrics.ready();\nconst variant = MostlyGoodMetrics.getVariant('button-color', 'control');\n```\n\nIn local mode the SDK fetches only the experiment *configurations* (`GET /v1/experiments/configs` - a list of `{ id, name, variants }` with no user-specific data; the request carries no `user_id` or `anonymous_id`), and assigns the variant on-device.\n\n### Inline mode (zero network)\n\nProvide the configurations inline and the SDK makes no experiments network request at all:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  experimentMode: 'local',\n  localExperiments: [\n    {\n      id: '7b1e8a90-4c2d-4f6a-9e3b-2a1d5c8f0e71', // experiment UUID from the dashboard\n      name: 'button-color',\n      variants: ['control', 'treatment'],\n    },\n  ],\n});\n```\n\n### The bucketing algorithm\n\nLocal assignment is deterministic and identical across all MGM SDKs (Swift, Android, Flutter, JavaScript):\n\n```\nbucket  = first 8 bytes of SHA-256(utf8(\"<experiment_uuid>:<user_id>\"))\n          interpreted as an unsigned big-endian 64-bit integer\nvariant = variants[bucket % variants.length]\n```\n\n`user_id` is the identified user ID if `identify()` has been called, otherwise the anonymous ID. Because the bucket value exceeds `Number.MAX_SAFE_INTEGER`, the SDK computes it with `BigInt`. SHA-256 is computed by a small vendored synchronous implementation (no dependencies; works in browsers, Node.js, React Native and Capacitor webviews, where WebCrypto's async `crypto.subtle` is not universally available). The implementation is locked down by golden-vector tests shared across all SDKs.\n\n### Stickiness\n\nThe first variant resolved for an experiment is persisted (keyed by experiment UUID) and reused on subsequent `getVariant()` calls and across restarts. **`identify()` never re-buckets**: a user who was assigned `control` anonymously keeps `control` after logging in, even though their effective user ID changed. A persisted variant is only discarded if it no longer exists in the experiment's variants list, or when the identity is reset via `resetAnonymousId()` or the forget-me `resetIdentity({ clearAnonymousId: true })` (see [Privacy](#privacy)) - a fresh identity is re-bucketed.\n\n### Exposure tracking\n\nUnchanged from server mode: on a `getVariant()` hit the variant is stored as a `$experiment_{name}` super property and a `$experiment_exposure` event is tracked once per (user, experiment, variant), with the raw experiment name.\n\n### Caveats\n\n- **No cross-device consistency for anonymous users**: bucketing keys on the local effective user ID, and there is no server-side alias resolution. A user who is anonymous on one device and identified on another may see different variants until they are identified everywhere (identified users get consistent variants on every device, for experiments first evaluated after login).\n- **Config changes**: reordering or removing variants changes assignments for new users (existing sticky assignments are kept while the variant still exists).\n\n## Automatic Behavior\n\nThe SDK handles many tasks automatically to provide a seamless analytics experience:\n\n### Identity Management\n- **Generates anonymous user ID**: Creates a persistent UUID on first visit, stored in cookies + localStorage\n- **Persists identified user ID**: Stores user ID (from `identify()`) in cookies + localStorage, automatically restored on page reload\n- **Generates session IDs**: Creates a new UUID on each page load to track user sessions\n\n### Event Storage & Delivery\n- **Persists events**: Stores events in localStorage (with in-memory fallback if unavailable)\n- **Batches events**: Groups events together for efficient network usage (default: 100 events per batch)\n- **Flushes on interval**: Automatically sends events every 30 seconds (configurable via `flushInterval`)\n- **Flushes on visibility change**: Sends pending events when tab is hidden or page unloads\n- **Compresses payloads**: Large batches (>1KB) are automatically gzip compressed\n- **Retries on failure**: Preserves events on network errors and retries with exponential backoff\n- **Handles rate limiting**: Automatically backs off when server rate limits are hit\n- **Adds deduplication IDs**: Includes unique `client_event_id` with each event to prevent duplicate processing\n- **Offline support**: Events queue locally when offline and send when connectivity returns\n\n`reset()` and `destroy()` stop SDK timers and abort SDK-owned requests. Page-view\ncapture remains best effort when browser metadata or hooks are unavailable;\nSDK capture failures do not interrupt native navigation. MGM restores only its\nown history wrappers and preserves router hooks installed afterward. Repeated\nidentity refreshes cancel the previous experiment request, and late responses\ncannot replace assignments for a newer identity.\n\n### Lifecycle Tracking\nWhen `trackAppLifecycleEvents` is enabled, the SDK automatically:\n- **Detects install**: Tracks `$app_installed` event on first visit (requires `appVersion` config)\n- **Detects updates**: Tracks `$app_updated` event when app version changes (requires `appVersion` config)\n- **Tracks page visibility**: Fires `$app_opened` when page becomes visible\n- **Tracks page hidden**: Fires `$app_backgrounded` when page is hidden or unloads\n\n### Platform Integration\n- **Detects device type**: Automatically identifies desktop, phone, or tablet from user agent and screen size\n- **Captures browser info**: Includes browser name and version with every event\n- **Captures OS info**: Includes operating system name and version with every event\n- **Captures screen dimensions**: Includes screen and viewport size for UI analytics\n- **Captures locale**: Includes user's language/region setting\n- **Captures timezone**: Includes user's timezone for accurate time-based analysis\n\n## Debug Logging\n\nEnable debug logging to see SDK activity:\n\n```typescript\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  enableDebugLogging: true,\n});\n```\n\nOutput example:\n```\n[MostlyGoodMetrics] [INFO] MostlyGoodMetrics initialized with environment: production\n[MostlyGoodMetrics] [DEBUG] Tracking event: button_clicked\n[MostlyGoodMetrics] [DEBUG] Starting flush\n[MostlyGoodMetrics] [DEBUG] Successfully sent 5 events\n```\n\n## Framework Integration\n\nThe SDK supports both JavaScript and TypeScript projects. All type definitions are included automatically.\n\n### React\n\n```typescript\n// src/analytics.ts\nimport { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';\n\nexport function initAnalytics() {\n  MostlyGoodMetrics.configure({\n    apiKey: process.env.REACT_APP_MGM_API_KEY!,\n    environment: process.env.NODE_ENV,\n    appVersion: process.env.REACT_APP_VERSION,\n  });\n}\n\n// src/index.tsx\nimport { initAnalytics } from './analytics';\ninitAnalytics();\n```\n\n### Next.js\n\n```typescript\n// lib/analytics.ts\nimport { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';\n\nexport function initAnalytics() {\n  if (typeof window !== 'undefined') {\n    MostlyGoodMetrics.configure({\n      apiKey: process.env.NEXT_PUBLIC_MGM_API_KEY!,\n      environment: process.env.NODE_ENV,\n    });\n  }\n}\n\n// app/layout.tsx or pages/_app.tsx\n'use client';\nimport { useEffect } from 'react';\nimport { initAnalytics } from '@/lib/analytics';\n\nexport default function RootLayout({ children }) {\n  useEffect(() => {\n    initAnalytics();\n  }, []);\n\n  return <html>...</html>;\n}\n```\n\n### Vue\n\n```typescript\n// src/plugins/analytics.ts\nimport { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';\n\nexport default {\n  install() {\n    MostlyGoodMetrics.configure({\n      apiKey: import.meta.env.VITE_MGM_API_KEY,\n      environment: import.meta.env.MODE,\n    });\n  }\n};\n\n// src/main.ts\nimport analytics from './plugins/analytics';\napp.use(analytics);\n```\n\n## Custom Storage\n\nYou can provide a custom storage adapter for environments where localStorage isn't available:\n\n```typescript\nimport { MostlyGoodMetrics, IEventStorage, InMemoryEventStorage } from '@mostly-good-metrics/javascript';\n\n// Use in-memory storage\nMostlyGoodMetrics.configure({\n  apiKey: 'mgm_proj_your_api_key',\n  storage: new InMemoryEventStorage(10000),\n});\n\n// Or implement your own\nclass MyCustomStorage implements IEventStorage {\n  async store(event: MGMEvent): Promise<void> { /* ... */ }\n  async fetchEvents(limit: number): Promise<MGMEvent[]> { /* ... */ }\n  // clientEventIds contains the stable IDs of the successfully sent events.\n  // Prefer removing by ID so concurrent queue changes cannot remove unsent events.\n  async removeEvents(count: number, clientEventIds?: string[]): Promise<void> { /* ... */ }\n  async eventCount(): Promise<number> { /* ... */ }\n  async clear(): Promise<void> { /* ... */ }\n}\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}