{"_id":"@amirafa/vuexp","_rev":"8-6aa82a39741f38349a368c21d2ffa60c","name":"@amirafa/vuexp","dist-tags":{"latest":"1.0.7"},"versions":{"1.0.0":{"name":"@amirafa/vuexp","version":"1.0.0","_id":"@amirafa/vuexp@1.0.0","maintainers":[{"name":"amirafa","email":"amir.h.rafati@gmail.com"}],"dist":{"shasum":"d6237710abcaaf95d4f9babda4d77d5ba0335a30","tarball":"https://registry.npmjs.org/@amirafa/vuexp/-/vuexp-1.0.0.tgz","fileCount":26,"integrity":"sha512-0QmkTV48B1YAY9fJarak1k3V1MJGurBNBkEZ17PBwou8kV/ArIIiAjkv1peT6BPZsUqwMVJoEGVG+SBmO4GEaw==","signatures":[{"sig":"MEQCID1GQcueRKfN2PW2WikoQb2rEBo5sSXdKN4N/lkTHIBoAiB66I4mfzCgp4pxy8NOis0AUMqnkaFBIv0DQ2CeNVJDfw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":113727},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs"}},"gitHead":"75c43c194e5c7f0cdfa1006a96014eb65edd238b","scripts":{"build":"vite build && vue-tsc -p tsconfig.json --noEmit false","buildev":"npm run build && cd playground && npm i ../ && npm run dev","typecheck":"vue-tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"amirafa","email":"amir.h.rafati@gmail.com"},"_npmVersion":"11.4.0","description":"Lightweight Vue 3 plugin for A/B testing and experiments with variant tracking.","directories":{},"sideEffects":false,"_nodeVersion":"22.15.0","_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.0.0","typescript":"^5.5.0","vite-plugin-dts":"^4.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/vuexp_1.0.0_1760823544583_0.7608885014734741","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@amirafa/vuexp","version":"1.0.1","author":{"name":"Amirafa","email":"amir.h.rafati@gmai;.com"},"license":"MIT","_id":"@amirafa/vuexp@1.0.1","maintainers":[{"name":"amirafa","email":"amir.h.rafati@gmail.com"}],"dist":{"shasum":"3d62e1c2d4393b743241c172699b67f18432ce19","tarball":"https://registry.npmjs.org/@amirafa/vuexp/-/vuexp-1.0.1.tgz","fileCount":27,"integrity":"sha512-PwRdBVzlxQHwmDLBMh2D2tOu8JAssseX3IdtNNvyeoHlkGJyvzKtawtkg594LRsoOz9FTWzX7rs3VLv1jbRXjg==","signatures":[{"sig":"MEUCIQC1PfmkqDr4WGuUUmWjFvnDEWRtYhgKFWc6+kgCCBO+PwIgdT4510m0JCum90JZA8Mb95VdflNj8iVyakFn7BGZUHc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":115182},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs"}},"gitHead":"9d69125b67967ff86e1051040d876146ffcb7c86","scripts":{"build":"vite build && vue-tsc -p tsconfig.json --noEmit false","buildev":"npm run build && cd playground && npm i ../ && npm run dev","typecheck":"vue-tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"amirafa","email":"amir.h.rafati@gmail.com"},"_npmVersion":"11.4.0","description":"Lightweight Vue 3 plugin for A/B testing and experiments with variant tracking.","directories":{},"sideEffects":false,"_nodeVersion":"22.15.0","_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.0.0","typescript":"^5.5.0","vite-plugin-dts":"^4.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/vuexp_1.0.1_1760824735564_0.3132046251946228","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@amirafa/vuexp","version":"1.0.2","author":{"name":"Amirafa","email":"amir.h.rafati@gmai;.com"},"license":"MIT","_id":"@amirafa/vuexp@1.0.2","maintainers":[{"name":"amirafa","email":"amir.h.rafati@gmail.com"}],"dist":{"shasum":"546195d4a0af13eb226d49ea3b7c769158a8e808","tarball":"https://registry.npmjs.org/@amirafa/vuexp/-/vuexp-1.0.2.tgz","fileCount":27,"integrity":"sha512-NayG37p/Um5UAjAKTnXp1Y25eCXUi+Zcr8KqKBC0N2Z6wAwSDkf7JDFi5P0qHl9FYQRqI9qI33o/ssWrd2vCJQ==","signatures":[{"sig":"MEQCIGzjgswO6sCjFwp/ezDKWAsOLG4VWQ0y0ksCja3IEUnYAiASPQrSJfQzeZEUr8WsiJGBHd6ASuY2y/ZMUfsayaqMBw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":115258},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs"}},"gitHead":"5a3ea7eb64ac7abfffc24da3a694842dd090531a","scripts":{"build":"vite build && vue-tsc -p tsconfig.json --noEmit false","buildev":"npm run build && cd playground && npm i ../ && npm run dev","typecheck":"vue-tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"amirafa","email":"amir.h.rafati@gmail.com"},"_npmVersion":"11.4.0","description":"Lightweight Vue 3 plugin for A/B testing and experiments with variant tracking.","directories":{},"sideEffects":false,"_nodeVersion":"22.15.0","_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.0.0","typescript":"^5.5.0","vite-plugin-dts":"^4.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/vuexp_1.0.2_1760825024839_0.9696536291581557","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@amirafa/vuexp","version":"1.0.3","author":{"name":"Amirafa","email":"amir.h.rafati@gmai;.com"},"license":"MIT","_id":"@amirafa/vuexp@1.0.3","maintainers":[{"name":"amirafa","email":"amir.h.rafati@gmail.com"}],"dist":{"shasum":"aa2019168ed4909d6f01d265822286be0184cc21","tarball":"https://registry.npmjs.org/@amirafa/vuexp/-/vuexp-1.0.3.tgz","fileCount":27,"integrity":"sha512-3+ehCqv2yp4mlZ/oLZAvQHgM9BaTNWfVu8MtDGX6rzEIYu3WnYDoZQwtfZFQxp5a9dvNN61W4nRu9K/4WSgmhg==","signatures":[{"sig":"MEUCIByYkQHj1q60kHrjiYL5HDOZALTOq4ldBBFXMlg2zTnjAiEA5CVE4mlsOwQGQlREb5WseaM/3Pc9DnE12vsKs1NI8Xs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":121596},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs"}},"gitHead":"7998cf4cad6be86ad24b2ad53557225274ad15b3","scripts":{"build":"vite build && vue-tsc -p tsconfig.json --noEmit false","buildev":"npm run build && cd playground && npm i ../ && npm run dev","typecheck":"vue-tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"amirafa","email":"amir.h.rafati@gmail.com"},"_npmVersion":"11.4.1","description":"Lightweight Vue 3 plugin for A/B testing and experiments with variant tracking.","directories":{},"sideEffects":false,"_nodeVersion":"22.11.0","_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.0.0","typescript":"^5.5.0","vite-plugin-dts":"^4.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/vuexp_1.0.3_1760875293813_0.10505924313320114","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@amirafa/vuexp","version":"1.0.4","author":{"name":"Amirafa","email":"amir.h.rafati@gmai;.com"},"license":"MIT","_id":"@amirafa/vuexp@1.0.4","maintainers":[{"name":"amirafa","email":"amir.h.rafati@gmail.com"}],"dist":{"shasum":"f82f51d7cab468ec7cab617b25294db8e8922472","tarball":"https://registry.npmjs.org/@amirafa/vuexp/-/vuexp-1.0.4.tgz","fileCount":27,"integrity":"sha512-L1j/tpXQc7WiLtFOOM+6Ueb2BeYfEz+iisVukRjimKJnU1K4JWg6HdJYmCyG95irZJL6AMQtnE1VXHm5oCXU4g==","signatures":[{"sig":"MEUCIQC8Vt9AuzUgGH+Dg9UWMFKTJYX4E9nUImuHapUAI4IXVgIgWlyRYTot8k1DVeRxMuqBfbq6mzUqZ0Eu53kGlRkzx1k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":123718},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs"}},"gitHead":"c5219e32d70721bdb1eb8334892d88a64e0119c3","scripts":{"build":"vite build && vue-tsc -p tsconfig.json --noEmit false","buildev":"npm run build && cd playground && npm i ../ && npm run dev","typecheck":"vue-tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"amirafa","email":"amir.h.rafati@gmail.com"},"_npmVersion":"11.4.1","description":"Lightweight Vue 3 plugin for A/B testing and experiments with variant tracking.","directories":{},"sideEffects":false,"_nodeVersion":"22.11.0","_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.0.0","typescript":"^5.5.0","vite-plugin-dts":"^4.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/vuexp_1.0.4_1760962491967_0.9940485388350433","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@amirafa/vuexp","version":"1.0.5","author":{"name":"Amirafa","email":"amir.h.rafati@gmai;.com"},"license":"MIT","_id":"@amirafa/vuexp@1.0.5","maintainers":[{"name":"amirafa","email":"amir.h.rafati@gmail.com"}],"dist":{"shasum":"2e61ba0257d2aa3d4f035d12a24884a731b33df9","tarball":"https://registry.npmjs.org/@amirafa/vuexp/-/vuexp-1.0.5.tgz","fileCount":29,"integrity":"sha512-L8qW/Jxrrb/GTQeMKbc3MYjAraHEx7j9hx1N5cEt4E1ZOm/udiDmP8sR7UA2icu9ZAqQqOD1D13KDSBPP7uLRA==","signatures":[{"sig":"MEYCIQD5iLcq4OVllPio1oWKpLQ1BLzv943fWiasEOEy0MvuEQIhAOiG+Asp9NVOZOEF4eVeMhULoCxEQJQs3ckiWOk08MCw","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":144275},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs"}},"gitHead":"1d3d69719bc0c1e88533822ff8f69df4dfec71fb","scripts":{"build":"vite build && vue-tsc -p tsconfig.json --noEmit false","buildev":"npm run build && cd playground && npm i ../ && npm run dev","typecheck":"vue-tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"amirafa","email":"amir.h.rafati@gmail.com"},"_npmVersion":"11.4.1","description":"Lightweight Vue 3 plugin for A/B testing and experiments with variant tracking.","directories":{},"sideEffects":false,"_nodeVersion":"22.11.0","_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.0.0","typescript":"^5.5.0","vite-plugin-dts":"^4.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/vuexp_1.0.5_1761033182811_0.46776016113808483","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@amirafa/vuexp","version":"1.0.6","author":{"name":"Amirafa","email":"amir.h.rafati@gmai;.com"},"license":"MIT","_id":"@amirafa/vuexp@1.0.6","maintainers":[{"name":"amirafa","email":"amir.h.rafati@gmail.com"}],"dist":{"shasum":"528dc9f6a9072d5368c3f4f164eee050355bdeef","tarball":"https://registry.npmjs.org/@amirafa/vuexp/-/vuexp-1.0.6.tgz","fileCount":29,"integrity":"sha512-tw1/MpWOumlagTUon0WPqYRK3Gp81ZHMTV8RljmrlzbG/MxYDDS+dKjM8iQF3Gdshxjloc2RAn75I75U0VeyrQ==","signatures":[{"sig":"MEUCIBvl3x53hu4jsRbcaKCMQVsqYjYsRAdO/4Ct0pUhhC9OAiEAtlxMU/Eoo2XlXYojWf8OPZdl7vwhLNaSMh/BC4HSR+M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":176284},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs"}},"gitHead":"c826d50c94466ead17f5f21423a35b2d54afc9ec","scripts":{"build":"vite build && vue-tsc -p tsconfig.json --noEmit false && javascript-obfuscator dist --output dist","buildev":"cd playground && npm i ../ && npm run dev","typecheck":"vue-tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"amirafa","email":"amir.h.rafati@gmail.com"},"_npmVersion":"11.4.1","description":"Lightweight Vue 3 plugin for A/B testing and experiments with variant tracking.","directories":{},"sideEffects":false,"_nodeVersion":"22.11.0","_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.0.0","typescript":"^5.5.0","vite-plugin-dts":"^4.0.0","@vitejs/plugin-vue":"^5.0.0","javascript-obfuscator":"^4.1.1"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/vuexp_1.0.6_1761034276498_0.011053010164421506","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"@amirafa/vuexp","version":"1.0.7","description":"Lightweight Vue 3 plugin for A/B testing and experiments with variant tracking.","license":"MIT","author":{"name":"Amirafa","email":"amir.h.rafati@gmail.com"},"publishConfig":{"access":"public"},"keywords":["vuexp","vue","vue3","testing","a/b testing","experiment"],"type":"module","main":"./dist/index.cjs","module":"./dist/index.es.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs"}},"sideEffects":false,"peerDependencies":{"vue":"^3.4.0"},"devDependencies":{"@vitejs/plugin-vue":"^5.0.0","javascript-obfuscator":"^4.1.1","typescript":"^5.5.0","vite":"^5.0.0","vite-plugin-dts":"^4.0.0","vue":"^3.4.0","vue-tsc":"^2.0.0"},"scripts":{"build":"vite build && vue-tsc -p tsconfig.json --noEmit false && javascript-obfuscator dist --output dist","typecheck":"vue-tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run build","buildev":"cd playground && npm i ../ && npm run dev"},"_id":"@amirafa/vuexp@1.0.7","gitHead":"04fe0e0b2dc7f1522cc19a7a2d1e1e02f12c9c42","_nodeVersion":"20.15.0","_npmVersion":"10.7.0","dist":{"integrity":"sha512-XGc0PBocZGSO2dR6GcubRx3JtAcU2aMdWJeBw3fPBuSRtDQWzOCt4it5L2Dc/TNHR59Vwrnvf+nR60bgie5rvw==","shasum":"b904ce29f79b1dda91e68ec8183baabaf0a7615f","tarball":"https://registry.npmjs.org/@amirafa/vuexp/-/vuexp-1.0.7.tgz","fileCount":31,"unpackedSize":191166,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEKTp2iEpjAS4LKx5ydu++KYsM5sZ+YIcFM1oVUT45hUAiEAw9qDKNnXeggUMSB2iBWHULK7dyZOZ8SCJsofiR6uKAU="}]},"_npmUser":{"name":"amirafa","email":"amir.h.rafati@gmail.com"},"directories":{},"maintainers":[{"name":"amirafa","email":"amir.h.rafati@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vuexp_1.0.7_1761335498781_0.9767832653414334"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-18T21:39:04.520Z","modified":"2025-10-24T19:51:39.207Z","1.0.0":"2025-10-18T21:39:04.792Z","1.0.1":"2025-10-18T21:58:55.761Z","1.0.2":"2025-10-18T22:03:45.072Z","1.0.3":"2025-10-19T12:01:34.044Z","1.0.4":"2025-10-20T12:14:52.153Z","1.0.5":"2025-10-21T07:53:02.986Z","1.0.6":"2025-10-21T08:11:16.705Z","1.0.7":"2025-10-24T19:51:38.974Z"},"author":{"name":"Amirafa","email":"amir.h.rafati@gmail.com"},"license":"MIT","description":"Lightweight Vue 3 plugin for A/B testing and experiments with variant tracking.","maintainers":[{"name":"amirafa","email":"amir.h.rafati@gmail.com"}],"readme":"<p align=\"center\">\r\n  <a href='https://postimages.org/' target='_blank'>\r\n    <img \r\n      src='https://i.postimg.cc/mZqFZ4k5/vuexp-logo.png'       \r\n      width=\"256\" \r\n      height=\"256\"  \r\n      border='0' \r\n      alt='vuexp-logo'\r\n    />\r\n  </a>\r\n</p>\r\n# 🧪 Vuexp — Lightweight A/B Testing Plugin for Vue 3\r\n\r\n**Vuexp** is a lightweight and flexible Vue 3 plugin for A/B testing.  \r\nIt helps you define experiments, control variant traffic, track user behavior, and manage exposure — all directly within your Vue components.\r\n\r\n---\r\n\r\n## 📚 Table of Contents\r\n<details open>\r\n<summary>Click to expand</summary>\r\n\r\n- [📦 Installation](#-installation)\r\n- [🧠 Fundamentals](#-fundamentals)\r\n- [⚙️ Setup](#️-setup)\r\n  - [🔺 Config Priority](#-config-priority)\r\n- [🧩 Usage](#-usage)\r\n  - [a) Component with Props](#a-component-with-props)\r\n  - [b) Component with Slots](#b-component-with-slots)\r\n  - [c) Component with Slot Props](#c-component-with-slot-props)\r\n  - [d) Composable: useExperiment](#d-composable-useexperiment)\r\n- [🧾 Experiment Props](#-experiment-props)\r\n- [🧩 Component Expose](#-component-expose)\r\n- [🎧 Component Emits](#-component-emits)\r\n- [📡 Tracking System](#-tracking-system)\r\n  - [Global Tracking (onTrack)](#global-tracking-ontrack)\r\n  - [🧩 Tracking Priority](#-tracking-priority)\r\n  - [⏱️ Track Modes](#️-track-modes)\r\n  - [📤 Track Data Structure](#-track-data-structure)\r\n- [🎯 Events](#-events)\r\n- [🌐 Remote Config Example](#-remote-config-example)\r\n- [🔄 Versioning & Cache Behavior](#-versioning--cache-behavior)\r\n- [🧮 Holdout Group](#-holdout-group)\r\n- [👤 Setting User Context](#-setting-user-context)\r\n- [🐞 Debug Mode](#-debug-mode)\r\n- [💡 Best Practices](#-best-practices)\r\n- [📜 License](#-license)\r\n- [📅 Changelog](#changelog)\r\n\r\n</details>\r\n\r\n---\r\n\r\n## 📦 Installation\r\n\r\n```bash\r\nnpm install @amirafa/vuexp\r\n# or\r\nyarn add @amirafa/vuexp\r\n```\r\n\r\n---\r\n\r\n## 🧠 Fundamentals\r\n\r\nEach **A/B Test** can include multiple **Experiments**.  \r\nEvery **Experiment** decides which **Variant (A, B, etc.)** of your UI to show based on a statistical parameter called **Traffic**.\r\n\r\nFor example:\r\n\r\n```js\r\n// Example traffic definition\r\ntraffic: {\r\n  A: 0.6,\r\n  B: 0.4,\r\n}\r\n```\r\n\r\n-   The plugin will randomly assign a user to one of these variants based on the given probabilities.\r\n-   Variant **A** appears ~60% of the time, and **B** ~40%.\r\n-   If total traffic is less than `1.0` (e.g. `{ A: 0.6, B: 0.2 }`), the remaining ratio (`0.2`) becomes the **Holdout group**, which sees your defined `defaultVariant`.\r\n\r\n✅ Vuexp automatically normalizes the traffic and chooses holdouts for you.\r\n\r\n> Changing the `version` in the global config **flushes all saved experiments**, so users will get newly assigned variants the next time they appear.\r\n\r\n---\r\n\r\n## ⚙️ Setup\r\n\r\n```ts\r\n// main.ts or App.vue\r\nimport { createApp } from \"vue\";\r\nimport App from \"./App.vue\";\r\nimport { Vuexp } from \"@amirafa/vuexp\";\r\n\r\nconst app = createApp(App);\r\n\r\napp.use(Vuexp, {\r\n    version: \"1.0.0\", // Change to reset cached experiments\r\n    debug: true, // Show logs in console (optional)\r\n\r\n    // Optional remote config & tracking\r\n    experimentsFetchApi: \"https://example.com/config.php\",\r\n    experimentsTrackApi: \"https://example.com/track.php\",\r\n\r\n    userId: undefined, // optional -better to set it after login (setUserContext({userId:<user_id>}))\r\n    visitorId: \"abc123\", // optional - better to generate it based on browser\r\n\r\n    // Global onTrack callback (fires after each track)\r\n    onTrack(payload, response) {\r\n        console.log(\"[onTrack()] Payload Sent\", payload);\r\n        console.log(\"[onTrack()] Response Received\", response);\r\n    },\r\n\r\n    // Track mode options\r\n    trackMode: {\r\n        mode: \"interval\", // 'immediate' | 'interval'\r\n        interval: 10000, // flush interval in ms (optional)\r\n        batchSize: 2, // events per flush (optional)\r\n    },\r\n\r\n    // Default experiment fallback\r\n    default: {\r\n        variants: [\"A\", \"B\"],\r\n        defaultVariant: \"A\",\r\n        traffic: { A: 0.9, B: 0.6 },\r\n    },\r\n});\r\n\r\napp.mount(\"#app\");\r\n```\r\n\r\n---\r\n\r\n### 🔺 Config Priority\r\n\r\nVuexp decides experiment settings in this order:\r\n\r\n```\r\nRemote Fetch → Component Props → Global Config → Default\r\n```\r\n\r\n---\r\n\r\n## 🧩 Usage\r\n\r\nVuexp offers multiple ways to define experiments.\r\n\r\n---\r\n\r\n### a) Component with Props\r\n\r\n```vue\r\n<Experiment\r\n    experiment=\"experiment-button\"\r\n    :is=\"{ A: ButtonTypeA, B: ButtonTypeB }\"\r\n    :variants=\"['A', 'B']\"\r\n    :traffic=\"{ A: 0.6, B: 0.4 }\"\r\n/>\r\n```\r\n\r\n---\r\n\r\n### b) Component with Slots\r\n\r\n```vue\r\n<Experiment\r\n    experiment=\"experiment-button\"\r\n    :variants=\"['A', 'B']\"\r\n    :traffic=\"{ A: 0.6, B: 0.4 }\"\r\n>\r\n  <template #A>\r\n    <ButtonTypeA />\r\n  </template>\r\n\r\n  <template #B>\r\n    <ButtonTypeB />\r\n  </template>\r\n</Experiment>\r\n```\r\n\r\n---\r\n\r\n### c) Component with Slot Props\r\n\r\n```vue\r\n<Experiment\r\n    experiment=\"experiment-button\"\r\n    :variants=\"['A', 'B']\"\r\n    :traffic=\"{ A: 0.6, B: 0.4 }\"\r\n    v-slot=\"{ variant, track }\"\r\n>\r\n  <div\r\n    @click=\"\r\n      track('click', {\r\n        attributes: {\r\n          info: `[experiment-button] clicked at ${new Date().toISOString()}`,\r\n        },\r\n      })\r\n    \"\r\n  >\r\n    <ButtonTypeA v-if=\"variant === 'A'\" />\r\n    <ButtonTypeB v-else-if=\"variant === 'B'\" />\r\n    <span v-else>Holdout</span>\r\n  </div>\r\n</Experiment>\r\n```\r\n\r\n---\r\n\r\n### d) Composable: `useExperiment`\r\n\r\n```vue\r\n<template>\r\n    <div>\r\n        <ButtonTypeA v-if=\"variant === 'A'\" />\r\n        <ButtonTypeB v-if=\"variant === 'B'\" />\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { useExperiment } from \"@amirafa/vuexp\";\r\nimport ButtonTypeA from \"./ButtonTypeA.vue\";\r\nimport ButtonTypeB from \"./ButtonTypeB.vue\";\r\n\r\nconst { variant, track } = useExperiment(\"btn-use\", {\r\n    variants: [\"A\", \"B\"],\r\n    traffic: { A: 0.6, B: 0.4 },\r\n});\r\n</script>\r\n```\r\n\r\n---\r\n\r\n## 🧾 Experiment Props\r\n\r\n| Prop             | Type                        | Required | Description                       |\r\n| ---------------- | --------------------------- | -------- | --------------------------------- |\r\n| `experiment`     | `string`                    | ✅       | Unique experiment identifier      |\r\n| `variants`       | `string[]`                  | ❌       | Available variant names           |\r\n| `traffic`        | `Record<string, number>`    | ❌       | Variant probabilities (0–1)       |\r\n| `defaultVariant` | `string`                    | ❌       | Variant used for holdouts         |\r\n| `is`             | `Record<string, Component>` | ❌       | Map of variant keys to components |\r\n\r\n---\r\n\r\n## 🧩 Component Expose\r\n\r\nEach `<Experiment>` component exposes a `track()` method:\r\n\r\n```ts\r\ntrack(\r\n  event: \"exposure\" | \"click\" | \"mouseenter\" | \"mouseleave\" | string,\r\n  options?: {\r\n    attributes?: Record<string, any>;\r\n    immediate?: boolean;\r\n  }\r\n)\r\n```\r\n\r\nExample:\r\n\r\n```vue\r\n<Experiment\r\n    ref=\"experimentButtonRef\"\r\n    experiment=\"experiment-button\"\r\n    :is=\"{ A: ButtonTypeA, B: ButtonTypeB }\"\r\n    :variants=\"['A', 'B']\"\r\n    :traffic=\"{ A: 0.6, B: 0.4 }\"\r\n    @click=\"\r\n        experimentButtonRef.track('click', {\r\n            attributes: {\r\n                info: `[btn-slot] clicked at ${new Date().toISOString()}`,\r\n            },\r\n        })\r\n    \"\r\n/>\r\n```\r\n\r\n---\r\n\r\n## 🎧 Component Emits\r\n\r\n| Event                                       | Payload            |\r\n| ------------------------------------------- | ------------------ |\r\n| `\"click\"` / `\"mouseenter\"` / `\"mouseleave\"` | `{ track, event }` |\r\n\r\nExample:\r\n\r\n```vue\r\n<Experiment\r\n    experiment=\"experiment-button\"\r\n    :is=\"{ A: ButtonTypeA, B: ButtonTypeB }\"\r\n    :variants=\"['A', 'B']\"\r\n    :traffic=\"{ A: 0.6, B: 0.4 }\"\r\n    @click=\"\r\n        ({ track, event }) => {\r\n            console.log('Event:', event);\r\n            track('click', {\r\n                attributes: {\r\n                    info: `[experiment-button] clicked at ${new Date().toISOString()}`,\r\n                },\r\n            }).then((resp) => {\r\n                console.log('[payload]', resp.payload);\r\n                console.log('[response]', resp.response);\r\n            });\r\n        }\r\n    \"\r\n/>\r\n```\r\n\r\n---\r\n\r\n## 📡 Tracking System\r\n\r\nYou can track experiment data automatically or manually.\r\n\r\n### Global Tracking (`onTrack`)\r\n\r\n```ts\r\nonTrack(payload, response) {\r\n  console.log(\"[onTrack()] Payload Sent\", payload);\r\n  console.log(\"[onTrack()] Response Received\", response);\r\n}\r\n```\r\n\r\nIf `experimentsTrackApi` is defined, Vuexp sends the data to that endpoint and passes the response here.  \r\nOtherwise, only the payload is sent to `onTrack` (response = `undefined`).\r\n\r\n---\r\n\r\n### 🧩 Tracking Priority\r\n\r\n```\r\n1️⃣ Global onTrack()  →  2️⃣ Local track()\r\n```\r\n\r\nLocal `track()` calls always run **after** the global callback.\r\n\r\n---\r\n\r\n### ⏱️ Track Modes\r\n\r\n| Mode        | Description                                                          |\r\n| ----------- | -------------------------------------------------------------------- |\r\n| `immediate` | Sends the event right after `track()` is called                      |\r\n| `interval`  | Buffers events and sends them after a defined interval or batch size |\r\n\r\n> Even in interval mode, you can set `{ immediate: true }` per event to override behavior.\r\n\r\n---\r\n\r\n### 📤 Track Data Structure\r\n\r\nWhen you define a `experimentsTrackApi` endpoint in your plugin configuration,  \r\nVuexp automatically sends a **payload** containing detailed tracking information for every experiment event.\r\n\r\nEach record in the payload follows the type:\r\n\r\n```ts\r\nexport type ExperimentTrackRequestType = {\r\n    experiment: string; // Experiment name\r\n    variant: string; // Assigned variant (A, B, etc.)\r\n    version: string; // Event's version\r\n    event: EventType; // 'exposure', 'click', 'mouseenter', etc.\r\n    timestamp: number; // Unix timestamp of the event\r\n    user_id?: string | number; // Optional user ID\r\n    visitor_id?: string | number; // Optional visitor ID\r\n    attributes?: Record<string, any>; // Custom attributes (optional)\r\n};\r\n```\r\n\r\n-   `experiment`: The unique identifier of the experiment.\r\n-   `variant`: The variant that was displayed to the user.\r\n-   `version`: The version of the test in which the event was tracked.\r\n-   `event`: The event type that triggered tracking (e.g., `click`, `exposure`).\r\n-   `timestamp`: Captured automatically at the moment of tracking.\r\n-   `user_id` / `visitor_id`: Identifiers that you can set dynamically using [`setUserContext()`](#-setting-user-context).\r\n-   `attributes`: Any custom metadata or context (e.g., button label, page, session data, etc.).\r\n\r\nExample payload sent to your API:\r\n\r\n```json\r\n[\r\n    {\r\n        \"experiment\": \"experiment-button\",\r\n        \"variant\": \"A\",\r\n        \"version\": \"1.0.1\"\r\n        \"event\": \"click\",\r\n        \"timestamp\": 1739923200000,\r\n        \"user_id\": \"1000\",\r\n        \"visitor_id\": \"abc123\",\r\n        \"attributes\": {\r\n            \"info\": \"Clicked CTA in header\"\r\n        }\r\n    }\r\n]\r\n```\r\n\r\n> 💡 You can safely call `setUserContext()` at any time before or after plugin initialization — Vuexp automatically attaches the most recent `user_id` or `visitor_id` values to all future tracking events.\r\n\r\n---\r\n\r\n## 🎯 Events\r\n\r\nVuexp provides 4 main built-in event types:\r\n\r\n```\r\n\"exposure\" | \"click\" | \"mouseenter\" | \"mouseleave\"\r\n```\r\n\r\n-   **exposure** → fired automatically when an experiment first becomes visible\r\n-   **click**, **mouseenter**, **mouseleave** → can be triggered manually via `track()` or emits\r\n-   You can also use **custom event names** for advanced tracking.\r\n\r\nExample:\r\n\r\n```vue\r\n<Experiment\r\n    experiment=\"experiment-button\"\r\n    :is=\"{ A: ButtonTypeA, B: ButtonTypeB }\"\r\n    :variants=\"['A', 'B']\"\r\n    :traffic=\"{ A: 0.6, B: 0.4 }\"\r\n    @click=\"\r\n        ({ track }) =>\r\n            track('click', {\r\n                attributes: {\r\n                    info: `[experiment-button] clicked at ${new Date().toISOString()}`,\r\n                },\r\n            })\r\n    \"\r\n/>\r\n```\r\n\r\n---\r\n\r\n## 🌐 Remote Config Example\r\n\r\nYou can host your experiment configuration on a server:\r\n\r\n**GET** `https://example.com/config.php`\r\n\r\n```json\r\n{\r\n    \"experiments\": {\r\n        \"experiment-button\": {\r\n            \"variants\": [\"A\", \"B\"],\r\n            \"traffic\": { \"A\": 0.6, \"B\": 0.4 },\r\n            \"defaultVariant\": \"A\"\r\n        },\r\n        \"hero-banner\": {\r\n            \"variants\": [\"Large\", \"Compact\"],\r\n            \"traffic\": { \"Large\": 0.5, \"Compact\": 0.5 }\r\n        }\r\n    },\r\n    \"default\": {\r\n        \"variants\": [\"A\", \"B\"],\r\n        \"traffic\": { \"A\": 0.5, \"B\": 0.5 }\r\n    }\r\n}\r\n```\r\n\r\nVuexp will automatically merge these configs and use them with highest priority.\r\n\r\n---\r\n\r\n## 🔄 Versioning & Cache Behavior\r\n\r\n-   Each experiment’s variant is **persisted per version**.\r\n-   Updating `version` in your Vuexp config **flushes** previous variant assignments.\r\n-   This ensures that new configurations or traffic ratios are applied cleanly.\r\n\r\n---\r\n\r\n## 🧮 Holdout Group\r\n\r\nWhen total traffic < `1.0`, the remaining ratio is assigned to **Holdout** users —  \r\nthey see your `defaultVariant` and are excluded from experiment analysis.\r\n\r\nExample:\r\n\r\n```js\r\ntraffic: { A: 0.6, B: 0.2 } // 0.2 → Holdout\r\n```\r\n\r\n---\r\n\r\n### 👤 Setting User Context\r\n\r\nVuexp allows you to associate experiment tracking data with a specific **user** or **visitor**.  \r\nThis helps distinguish between logged-in users and anonymous sessions when sending tracking events.\r\n\r\nYou can set the userContext at GlobalConfig; But its better to leave it to the plugin to generate a unique id for **_visitor_**\r\n\r\n```\r\napp.use(Vuexp, {\r\n  ...\r\n  userId: undefined, //For logged-in users\r\n  visitorId: 'abc123', // Optional unique ID for guests\r\n  ...\r\n});\r\n```\r\n\r\nYou can update the userContext at any time — for example, right after user login or when visitor information becomes available.\r\n\r\n```ts\r\nimport { setUserContext } from \"@amirafa/vuexp\";\r\n\r\n// Example: set after authentication\r\nsetUserContext({\r\n    userId: 1000, // For logged-in users\r\n    visitorId: \"abc123\", // Optional unique ID for guests\r\n});\r\n```\r\n\r\nBehind the scenes, Vuexp keeps an internal reactive `state` used for tracking:\r\n\r\n```ts\r\nstate.value = {\r\n  ...\r\n  userId: string | undefined,    // Logged-in user identifier\r\n  visitorId: string | undefined, // Anonymous visitor identifier\r\n  ...\r\n};\r\n```\r\n\r\n-   `userId` and `visitorId` are sent automatically with every tracked event once set.\r\n-   `visitorId` is useful for anonymous visitors or guest sessions.\r\n-   You can safely call `setUserContext()` whenever user data becomes available — it will instantly update the tracking context used for all future events.\r\n\r\nExample integration in a login flow:\r\n\r\n```ts\r\n// After successful login\r\nlogin().then((user) => {\r\n    setUserContext({ userId: user.id });\r\n});\r\n```\r\n\r\n> 🧠 Tip: Call `setUserContext()` **once per session** or whenever user identity changes (e.g., login, logout, or switch account).\r\n\r\n## 🐞 Debug Mode\r\n\r\nSet `debug: true` in your config to see internal logs:\r\n\r\n```\r\n[Vuexp] Experiment: experiment-button → Variant: B\r\n[Vuexp] Track event: click { ...payload }\r\n```\r\n\r\nUseful for development and QA environments.\r\n\r\n---\r\n\r\n## 💡 Best Practices\r\n\r\n-   Use consistent experiment naming (`header-color`, `cta-button`, etc.)\r\n-   Bump `version` whenever changing traffic or variants\r\n-   Keep traffic ratios between 0–1; Vuexp normalizes automatically\r\n-   Use `immediate: true` for purchase or form events\r\n-   Enable remote config for dynamic updates without redeploys\r\n-   Use debug mode in staging to inspect assignments and payloads\r\n\r\n---\r\n\r\n## 📜 License\r\n\r\n[MIT](./LICENSE) © 2025 [Amirafa]\r\n\r\nSimple. Reliable. Vue-native A/B Testing.\r\n\r\n---\r\n\r\n## Changelog\r\n\r\n### [Version 1.0.7] - 2025-10-24\r\n\r\n#### Feature\r\n\r\n-   Update `storing variants` system\r\n\r\n### [Version 1.0.6] - 2025-10-21\r\n\r\n#### Feature\r\n\r\n-   Obfuscate dist\r\n\r\n### [Version 1.0.5] - 2025-10-21\r\n\r\n#### Feature\r\n\r\n-   Fix remote-config storage\r\n-   Obfuscate the experiments key/value\r\n\r\n### [Version 1.0.4] - 2025-10-20\r\n\r\n#### Feature\r\n\r\n-   Add version to track payload.\r\n-   Update README.md (Add vuexp logo)\r\n\r\n### [Version 1.0.3] - 2025-10-20\r\n\r\n#### Feature\r\n\r\n-   Add a feature that generates a unique visitor ID.\r\n-   Update README.md\r\n\r\n### [Version 1.0.2] - 2025-10-19\r\n\r\n#### Feature\r\n\r\n-   Add Changelog to README.md\r\n\r\n### [Version 1.0.1] - 2025-10-19\r\n\r\n#### Feature\r\n\r\n-   Add README.md documentation\r\n-   Add MIT Licence\r\n\r\n### [Version 1.0.0] - 2025-10-19\r\n\r\n#### Feature\r\n\r\n-   Release package\r\n\r\n---\r\n","readmeFilename":"README.md","keywords":["vuexp","vue","vue3","testing","a/b testing","experiment"]}