@koryla/netlify
v0.1.2
Published
A/B testing for Netlify sites with zero flicker. Runs on Netlify Edge Functions (Deno).
Readme
@koryla/netlify
A/B testing for Netlify sites with zero flicker. Runs on Netlify Edge Functions (Deno).
Installation
npm install @koryla/netlifySetup
1. Add environment variables
In your Netlify dashboard → Site settings → Environment variables:
KORYLA_API_KEY = sk_live_...
KORYLA_API_URL = https://koryla.com2. Create the edge function
// netlify/edge-functions/koryla.ts
import { korylaMiddleware } from '@koryla/netlify'
export default korylaMiddleware({
apiKey: Deno.env.get('KORYLA_API_KEY')!,
apiUrl: Deno.env.get('KORYLA_API_URL')!,
})
export const config = {
path: ['/', '/pricing', '/landing'],
}3. Create your variant pages
Your variant pages must be real pages in your site:
src/pages/
index.astro ← control (base_url: https://acme.com/)
variant-b.astro ← variant (target_url: https://acme.com/variant-b)Works with any Netlify-hosted framework: Astro, SvelteKit, Nuxt, plain HTML.
4. Create an experiment in Koryla
Go to your Koryla dashboard → New experiment:
| Field | Value |
|-------|-------|
| Base URL | https://acme.com/ |
| Variant A — Control | https://acme.com/ · 50% |
| Variant B | https://acme.com/variant-b · 50% |
| Conversion URL | https://acme.com/thank-you |
Set it to Active and you're done.
How it works
User visits /
│
▼
Netlify Edge Function (runs at Deno edge, before your site renders)
│
├── calls Koryla API once every 60s to get experiment config
├── reads koryla_sid cookie
│ ├── cookie present → use existing variant (sticky)
│ └── no cookie → assign variant by traffic weight
│
├── rewrites request to /variant-b via context.rewrite()
└── sets cookie for 30 days
│
▼
Netlify serves /variant-b content
Browser sees original URL (/) — no redirect, no flickerWhy this is better than VWO / Optimizely
| | VWO / Optimizely | @koryla/netlify | |--|--|--| | When variant is decided | In the browser, after JS loads | At the edge, before any HTML | | Flicker | Yes (page hides while swapping) | No | | Extra JS on page | ~80–150 KB | 0 KB | | Blockable by ad blockers | Yes | No | | Works without JS | No | Yes |
