add skills
Build and Deploy / build-and-deploy (push) Successful in 2m53s

This commit is contained in:
2026-05-18 08:39:42 +02:00
parent 92a80e8759
commit 57af0b8386
53 changed files with 10190 additions and 0 deletions
@@ -0,0 +1,223 @@
# CMS Integration Patterns
Integrating experimentation with your CMS enables content teams to run tests without developer intervention.
## Architecture Options
### 1. CMS-Managed Variants
Store experiment variants as content in the CMS.
**Pros:** Content team autonomy, version controlled
**Cons:** More complex queries, potential publish coordination
```typescript
// Experiment document
defineType({
name: 'experiment',
type: 'document',
fields: [
defineField({ name: 'name', type: 'string' }),
defineField({ name: 'status', type: 'string', options: {
list: ['draft', 'running', 'paused', 'concluded']
}}),
defineField({
name: 'variants',
type: 'array',
of: [{
type: 'object',
fields: [
defineField({ name: 'name', type: 'string' }),
defineField({ name: 'weight', type: 'number' }),
defineField({ name: 'content', type: 'reference', to: [{ type: 'page' }] }),
]
}]
}),
defineField({ name: 'startDate', type: 'datetime' }),
defineField({ name: 'endDate', type: 'datetime' }),
]
})
```
### 2. Field-Level Variants
Store variants as fields on the content document.
**Pros:** Simpler queries, content stays together
**Cons:** Less flexible, schema complexity
```typescript
defineType({
name: 'landingPage',
fields: [
defineField({ name: 'headline', type: 'string' }),
defineField({
name: 'headlineVariantB',
type: 'string',
description: 'A/B test variant (leave empty if not testing)'
}),
defineField({ name: 'activeExperiment', type: 'string' }),
]
})
```
### 3. External Experimentation Platform
Use dedicated tools (Optimizely, LaunchDarkly, VWO) with CMS content.
**Pros:** Robust analytics, proven platforms
**Cons:** Additional cost, integration complexity
```typescript
// CMS stores experiment IDs, platform handles assignment
defineField({
name: 'experimentId',
type: 'string',
description: 'Optimizely experiment ID'
})
```
## Implementation Pattern (CMS-Managed)
### 1. Experiment Schema
```typescript
defineType({
name: 'experiment',
type: 'document',
fields: [
defineField({ name: 'name', type: 'string', validation: r => r.required() }),
defineField({ name: 'hypothesis', type: 'text' }),
defineField({
name: 'status',
type: 'string',
options: { list: ['draft', 'running', 'concluded'] },
initialValue: 'draft'
}),
defineField({
name: 'variants',
type: 'array',
of: [{
type: 'object',
name: 'variant',
fields: [
defineField({ name: 'id', type: 'string' }),
defineField({ name: 'name', type: 'string' }),
defineField({ name: 'weight', type: 'number', initialValue: 50 }),
]
}],
validation: r => r.min(2).error('Need at least 2 variants')
}),
defineField({ name: 'targetPage', type: 'reference', to: [{ type: 'page' }] }),
defineField({ name: 'targetField', type: 'string' }),
]
})
```
### 2. Variant Content
```typescript
// On the page being tested
defineField({
name: 'experimentVariants',
type: 'array',
of: [{
type: 'object',
fields: [
defineField({ name: 'experimentId', type: 'reference', to: [{ type: 'experiment' }] }),
defineField({ name: 'variantId', type: 'string' }),
defineField({ name: 'headline', type: 'string' }),
// Other variant-specific fields
]
}]
})
```
### 3. Frontend Assignment
```typescript
// Middleware or server-side
function assignVariant(experimentId: string, variants: Variant[]): string {
// Check for existing assignment in cookie
const cookieKey = `exp_${experimentId}`
const existing = getCookie(cookieKey)
if (existing) return existing
// Random assignment based on weights
const rand = Math.random() * 100
let cumulative = 0
for (const variant of variants) {
cumulative += variant.weight
if (rand <= cumulative) {
setCookie(cookieKey, variant.id, { maxAge: 30 * 24 * 60 * 60 })
return variant.id
}
}
return variants[0].id
}
```
### 4. Query with Variant
```groq
*[_type == "page" && slug.current == $slug][0]{
...,
"experiment": experimentVariants[experimentId->status == "running"][0]{
experimentId->{name, _id},
variantId,
headline
}
}
```
## Analytics Integration
### Event Tracking
```typescript
// Track experiment exposure
function trackExposure(experimentId: string, variantId: string) {
analytics.track('Experiment Viewed', {
experimentId,
variantId,
timestamp: new Date().toISOString()
})
}
// Track conversion
function trackConversion(experimentId: string, variantId: string, metric: string) {
analytics.track('Experiment Conversion', {
experimentId,
variantId,
metric,
timestamp: new Date().toISOString()
})
}
```
### Data Layer
```typescript
// Push to data layer for analytics tools
window.dataLayer.push({
event: 'experiment_assignment',
experiment_id: experimentId,
variant_id: variantId
})
```
## Best Practices
### Content Team Workflow
1. Create experiment document with hypothesis
2. Create variant content
3. Set status to "running"
4. Monitor results
5. Set status to "concluded" and record winner
### Avoid Flicker
- Assign variants server-side when possible
- Use CSS to hide content until variant determined
- Pre-render both variants, show based on assignment
### Clean Up
- Archive concluded experiments
- Remove losing variant content
- Implement winner as default