@thewishlistco/preference-widget
v1.1.3
Published
A JavaScript library for managing customer preferences with The Wishlist API. This widget handles preference logic and API integration while giving developers full control over the UI presentation.
Downloads
13
Readme
🛠️ Preference Widget
A JavaScript library for managing customer preferences with The Wishlist API. This widget handles preference logic and API integration while giving developers full control over the UI presentation.
📦 Installation
Option 1: CDN (Recommended)
<script src="https://unpkg.com/@thewishlistco/preference-widget@latest/script.js"></script>Option 2: NPM
npm install @thewishlistco/preference-widgetimport PreferenceWidget from "@thewishlistco/preference-widget";Option 3: Download
Download script.js and include it in your project:
<script src="path/to/script.js"></script>🚀 Quick Start
1. Initialize the Widget
const widget = new PreferenceWidget({
tenantId: "your-tenant-id",
customerEmail: "[email protected]",
});
// Initialize (loads preferences structure and customer data)
await widget.init();2. Get Category Options
// Get brand options
const brands = widget.getCategoryOptions("womens_brands");
console.log(brands);
// Returns: [{ id: 'adidas', value: 'Adidas', selected: true }, ...]
// Get any category
const colors = widget.getCategoryOptions("womens_colors");
const categories = widget.getCategoryOptions("womens_categories");3. Create Your UI
// Create buttons for each option
brands.forEach((option) => {
const button = document.createElement("button");
button.textContent = option.value;
button.className = option.selected ? "selected" : "";
// Handle clicks
button.onclick = async () => {
await widget.toggleOption("womens_brands", option.id);
button.classList.toggle("selected");
};
container.appendChild(button);
});⚙️ Configuration
| Parameter | Type | Required | Default | Description |
| --------------- | -------- | ---------- | ----------- | ----------------------------------------------------- |
| tenantId | string | ✅ Yes | - | Your unique tenant identifier from The Wishlist |
| customerEmail | string | No | null | Customer's email address for personalized preferences |
Example
const widget = new PreferenceWidget({
tenantId: "your-tenant-id",
customerEmail: "[email protected]",
});🔧 API Methods
init()
Initialize the widget and load data.
await widget.init();getCategoryOptions(categoryKey)
Get options for a specific preference category.
const options = widget.getCategoryOptions("womens_brands");
// Returns array of: { id: string, value: string, selected: boolean }
// If no customer email assigned, all options return selected: falsetoggleOption(categoryKey, optionId)
Toggle an option selection and save to API.
await widget.toggleOption("womens_brands", "adidas");
// Throws error if no customer email assignedassignCustomerEmail(customerEmail)
Assign customer email and load their preferences.
await widget.assignCustomerEmail("[email protected]");
// Loads customer data and preferences, enables toggling📝 Complete Examples
Example 1: With Customer Email (Logged-in User)
<!DOCTYPE html>
<html>
<head>
<title>Brand Preferences - Logged In</title>
<style>
.option-button {
padding: 12px 16px;
border: 2px solid #e1e5e9;
background: white;
cursor: pointer;
margin: 4px;
}
.option-button.selected {
border-color: #007bff;
background: #f8f9ff;
color: #007bff;
}
</style>
</head>
<body>
<h2>Your Brand Preferences</h2>
<div id="brands-container"></div>
<script src="https://unpkg.com/@thewishlistco/preference-widget@latest/script.js"></script>
<script>
async function initializePreferences() {
const widget = new PreferenceWidget({
tenantId: "your-tenant-id",
customerEmail: "[email protected]",
});
await widget.init();
renderBrands(widget);
}
function renderBrands(widget) {
const brands = widget.getCategoryOptions("womens_brands");
const container = document.getElementById("brands-container");
container.innerHTML = "";
brands.forEach((brand) => {
const button = document.createElement("button");
button.className = `option-button ${brand.selected ? "selected" : ""}`;
button.textContent = brand.value;
button.onclick = async () => {
try {
await widget.toggleOption("womens_brands", brand.id);
button.classList.toggle("selected");
} catch (error) {
alert(error.message);
}
};
container.appendChild(button);
});
}
initializePreferences().catch(console.error);
</script>
</body>
</html>Example 2: Guest User with Login
<!DOCTYPE html>
<html>
<head>
<title>Brand Preferences - Guest to Logged In</title>
<style>
.option-button {
padding: 12px 16px;
border: 2px solid #e1e5e9;
background: white;
cursor: pointer;
margin: 4px;
}
.option-button.selected {
border-color: #007bff;
background: #f8f9ff;
color: #007bff;
}
.option-button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.login-section {
margin-bottom: 20px;
padding: 16px;
background: #f8f9fa;
border-radius: 8px;
}
</style>
</head>
<body>
<div class="login-section">
<div id="guest-state">
<h3>You're browsing as a guest</h3>
<p>Login to save your preferences</p>
<input type="email" id="email-input" placeholder="Enter your email" />
<button onclick="loginUser()">Login</button>
</div>
<div id="logged-in-state" style="display: none;">
<h3>Welcome back!</h3>
<p>Your preferences are saved automatically.</p>
<button onclick="logoutUser()">Logout</button>
</div>
</div>
<h2>Brand Preferences</h2>
<div id="brands-container"></div>
<script src="https://unpkg.com/@thewishlistco/preference-widget@latest/script.js"></script>
<script>
let widget;
async function initializePreferences() {
// Initialize without customer email (guest user)
widget = new PreferenceWidget({
tenantId: "your-tenant-id",
});
await widget.init();
renderBrands();
}
function renderBrands() {
const brands = widget.getCategoryOptions("womens_brands");
const container = document.getElementById("brands-container");
container.innerHTML = "";
brands.forEach((brand) => {
const button = document.createElement("button");
button.className = `option-button ${brand.selected ? "selected" : ""}`;
button.textContent = brand.value;
// Disable buttons if no customer email
button.disabled = !widget.customerEmail;
button.onclick = async () => {
try {
await widget.toggleOption("womens_brands", brand.id);
button.classList.toggle("selected");
} catch (error) {
alert(error.message);
}
};
container.appendChild(button);
});
}
async function loginUser() {
const email = document.getElementById("email-input").value;
if (!email) {
alert("Please enter an email");
return;
}
try {
await widget.assignCustomerEmail(email);
// Update UI
document.getElementById("guest-state").style.display = "none";
document.getElementById("logged-in-state").style.display = "block";
// Re-render brands with customer preferences
renderBrands();
} catch (error) {
alert("Login failed: " + error.message);
}
}
function logoutUser() {
// Reset widget state
widget.customerEmail = null;
widget.customerId = null;
widget.customerPreferences = null;
widget.preferenceId = null;
// Update UI
document.getElementById("guest-state").style.display = "block";
document.getElementById("logged-in-state").style.display = "none";
document.getElementById("email-input").value = "";
// Re-render brands (all unselected and disabled)
renderBrands();
}
initializePreferences().catch(console.error);
</script>
</body>
</html>🔄 Data Flow
Guest User Flow
- Initialize widget with tenant only (no customer email)
- Authentication happens automatically
- Load preference structure from configuration API
- Get options with
getCategoryOptions()(all returnselected: false) - Assign customer email when user logs in with
assignCustomerEmail() - Load customer data and existing preferences
- Enable toggling and auto-save functionality
Logged-in User Flow
- Initialize widget with tenant and customer email
- Authentication happens automatically
- Load preference structure from configuration API
- Load customer data and existing preferences
- Filter options by region and availability
- Developer creates UI using
getCategoryOptions() - Handle user interactions with
toggleOption() - Auto-save changes to customer preferences
🛠 Framework Integration
React Example
import { useEffect, useState } from "react";
function BrandPreferences({ tenantId, customerEmail }) {
const [brands, setBrands] = useState([]);
const [widget, setWidget] = useState(null);
useEffect(() => {
async function initWidget() {
const preferenceWidget = new PreferenceWidget({
tenantId,
customerEmail,
});
await preferenceWidget.init();
const brandOptions = preferenceWidget.getCategoryOptions("womens_brands");
setWidget(preferenceWidget);
setBrands(brandOptions);
}
initWidget();
}, [tenantId, customerEmail]);
const handleToggle = async (brandId) => {
await widget.toggleOption("womens_brands", brandId);
// Update local state
setBrands((prev) => prev.map((brand) => (brand.id === brandId ? { ...brand, selected: !brand.selected } : brand)));
};
return (
<div>
<h2>Select Your Favorite Brands</h2>
{brands.map((brand) => (
<button key={brand.id} className={`brand-button ${brand.selected ? "selected" : ""}`} onClick={() => handleToggle(brand.id)}>
{brand.value}
</button>
))}
</div>
);
}