Updated the patch API to return full HTML instead of just text values. This allows the SDK to make more complex DOM changes beyond simple text replacements.
File: lib/firebase/experiments.ts
- Changed
controlText?: string→controlHtml?: string - Changed
variantText?: string→variantHtml?: string
File: app/api/experiments/[id]/patch/route.ts
Before:
{
"type": "text",
"selector": "#greeting",
"value": "Hello Sidiq"
}After:
{
"selector": "#greeting",
"newHtml": "<h1>Hello Sidiq</h1>"
}File: components/ExperimentSidePanel.tsx
- Changed state variables from
controlText/variantTexttocontrolHtml/variantHtml - Updated field labels from "Text" to "HTML"
- Changed input fields from single-line
<input>to multi-line<textarea>with monospace font - Extract full
outerHTMLinstead of justtextContentfrom selected element - Updated API request to send
controlHtml/variantHtml
File: app/api/experiments/route.ts
- Accept
controlHtml/variantHtmlin request body - Validate
controlHtml/variantHtmlinstead ofcontrolText/variantText - Pass HTML values to Firestore and Statsig
File: lib/statsig/api.ts
- Updated function signature to accept
controlHtml/variantHtml - Store HTML in Statsig parameter values as
htmlkey - Updated group metadata to include HTML content
GET /api/experiments/[experimentId]/patch?variantKey=control&userId=xxx
{
"selector": "#hero-title",
"newHtml": "<h1 class='text-4xl font-bold'>Hello, World!</h1>"
}// Fetch patch from API
const response = await fetch(
`https://dashboard.optivise.dev/api/experiments/${expId}/patch?variantKey=v1&userId=user123`
);
const patch = await response.json();
// Apply patch to DOM
const element = document.querySelector(patch.selector);
if (element) {
element.outerHTML = patch.newHtml;
}- Expect
{selector, newHtml}instead of{type, selector, value} - Use
outerHTMLassignment instead oftextContent
✅ More flexible - Can change entire elements, not just text
✅ Supports complex changes - Classes, attributes, nested elements
✅ Better UX - Shows full HTML in editor for transparency
✅ Cleaner API - Simpler response format
Control HTML:
<button class="btn btn-primary">Sign Up</button>Variant HTML:
<button class="btn btn-success btn-lg">Get Started Free!</button>Result: Complete button element replacement with different classes and text.
Test the updated API:
curl "http://localhost:3000/api/experiments/YOUR_EXP_ID/patch?variantKey=v1&userId=user123"Expected response:
{
"selector": "#target-element",
"newHtml": "<div>Your variant HTML here</div>"
}The SDK team needs to update their runtime logic:
- Fetch patch with same endpoint (no URL changes)
- Parse new response format
{selector, newHtml} - Apply using outerHTML:
element.outerHTML = patch.newHtml;
No changes needed to:
- Endpoint URL structure
- Query parameters
- CORS headers
- Authentication (still public)