@herazgo/varykit-vue

Vue 3 composable and component for VaryKit element-level multivariate testing.
1,171
Install
npm install @herazgo/varykit-vue
Latest Version:0.3.2
Vue:3
License:MIT
Last Updated:Sep 24, 2026
Links: npm
Maintainer: omidamraei

@herazgo/varykit-vue

Vue 3 composables and components for VaryKit element-level multivariate testing.

This package works in any Vue 3 app (Vite, plain Vue Router, etc.) with no Nuxt present. It declares vue as a peer dependency and depends on @herazgo/varykit-core for bucketing. For Nuxt, use @herazgo/varykit-nuxt — it has the same API shape but resolves experiments from nuxt.config instead of an app-level provider.

The experiment model

Tests are organized as named experiments. Each experiment defines its own segment universe and gets its own cookie (vary:<experiment>), so assignments are independent: a visitor can be hero: b and pricing: control at the same time. Configuration lives at app setup, provided by createVaryKit().

Install

pnpm add @herazgo/varykit-vue

Setup

import { createApp } from 'vue'
import { createVaryKit } from '@herazgo/varykit-vue'
import App from './App.vue'

createApp(App)
  .use(createVaryKit({
    experiments: {
      hero: {
        segments: { a: 0.5, b: 0.5 },
        endWith: 'b',
        endsAt: '2026-10-14T00:00:00Z'
      }
    }
  }))
  .mount('#app')

Usage

useVary(experiment)

Resolves the visitor's segment for the experiment, persisting it in the vary:<experiment> cookie so the assignment is sticky. Resolution happens once per app per experiment — every later useVary call and VaryShow/VaryHide instance sees the same segment.

<script setup>
import { useVary } from '@herazgo/varykit-vue'

const { segment } = useVary('hero')
</script>

<template>
  <p v-if="segment === 'a'">A content</p>
  <p v-else>B content</p>
</template>

<VaryShow>

Renders its default slot only when the visitor's segment for the experiment matches the segment prop.

<script setup>
import { VaryShow } from '@herazgo/varykit-vue'
</script>

<template>
  <VaryShow experiment="hero" segment="a">
    <p>A content</p>
  </VaryShow>

  <VaryShow experiment="hero" segment="b">
    <p>B content</p>
  </VaryShow>
</template>

<VaryHide>

The inverse of <VaryShow>: renders its default slot only when the visitor's segment does NOT match the segment prop.

<script setup>
import { VaryHide } from '@herazgo/varykit-vue'
</script>

<template>
  <VaryHide experiment="hero" segment="a">
    <p>Shown to everyone except segment a</p>
  </VaryHide>
</template>

Exposure events

The package emits an exposure event when a variant actually renders: a matching <VaryShow> / <VaryHide> slot. Register a handler once (e.g. next to createVaryKit):

import { onVaryExposure } from '@herazgo/varykit-vue'

onVaryExposure(({ experiment, segment }) => {
  // e.g. $analytics.track('experiment_viewed', { experiment, segment })
})

onVaryExposure returns an unregister function. No network calls, no dedup — wire your analytics tool and dedupe there.

Typed experiment and segment names

Augment the VaryExperiments interface once, and useVary returns a segment narrowed to that union:

// types/varykit.d.ts
declare module '@herazgo/varykit-vue' {
  interface VaryExperiments {
    hero: 'a' | 'b'
  }
}
const { segment } = useVary('hero') // segment: Ref<'a' | 'b'>

Limitation: vue-tsc 2.x/3.x does not instantiate generic function components in templates, so VaryShow/VaryHide props are checked loosely in templates while useVary stays strict. (The Nuxt module gets full template strictness via generated types.)

Lifecycle

Experiments support startsAt (default: immediate), endsAt (default: forever) and endWith — the terminal segment everyone gets outside the window:

Config Behavior
no endWith runs forever (until removed from config)
endWith only pinned immediately at setup
endWith + endsAt runs until the date, then pinned
endsAt without endWith setup error

The pin overrides existing sticky cookies and rewrites them on the next resolution, so "ended" means everyone — including previously assigned visitors — resolves to the declared segment. Exposure keeps firing with the pinned segment, so post-period conversions attribute cleanly. Lifecycle is evaluated at resolution time (once per app per experiment). Cookies are always persistent (400-day browser cap, refreshed on every resolution) — there are no cookie-duration knobs.

For content rendered via plain useVary branching (no VaryShow/VaryHide), emit manually when you decide the content was seen:

<script setup>
import { useVary, emitExposure } from '@herazgo/varykit-vue'

const { segment } = useVary('hero')

onMounted(() => {
  emitExposure('hero', segment.value)
})
</script>

For conversions, attach the segment to your own events.

Configuration

createVaryKit(options)

Option Type Description
experiments Record<string, Experiment> The experiment definitions, validated at setup.

Each experiment supports:

Option Type Description
segments Record<string, number> Segment weights between 0 and 1. Omitted segments auto-split the remainder.
startsAt string ISO date; the experiment accepts traffic from this moment. Default: immediate.
endsAt string ISO date; the experiment stops splitting traffic at this moment. Requires endWith.
endWith string Terminal segment everyone gets outside the [startsAt, endsAt] window.

Scope

This package owns Vue-specific persistence (document.cookie) and reactivity. It never imports from @herazgo/varykit-nuxt. It is client-side only — there is no SSR-safe story here; that is what the Nuxt module is for.

License

MIT

Related Packages

@herazgo/varykit-nuxt

Nuxt 4 module for VaryKit: file-based page testing plus SSR-safe element-level t...

1,549
nuxt-ab-testing

Nuxt module designed to seamlessly integrate A/B testing

2,902 18
vue-feature-toggles

Backend-agnostic feature flags for Vue 3 — boolean and multivariate flags, conte...

3,189 0
@beacon-hq/beam

Frontend helper for Laravel Pennant feature flags (with support for React and Vu...

3,379 47
@featurevisor/vue

Vue functions for Featurevisor flags, variations and configuration

6,724 812

Version History

Version Released License
0.3.2 MIT
0.3.1 MIT
0.3.0 MIT
0.2.1 MIT
0.2.0 MIT