Widget Configuration
The Neuroon widget is configured via data-* attributes on the script tag or through JavaScript.
Configuration with data attributes
<script
src="https://cdn.neuroon.ai/widget.js"
data-token="YOUR_TOKEN"
data-container="#neuroon-search"
data-theme="auto"
data-locale="en"
data-display-mode="fullscreen"
data-placeholder="What are you looking for?">
</script>
Available options
| Attribute | Type | Default | Description |
|---|---|---|---|
data-token | string | required | Widget authentication token |
data-container | string | required | CSS selector for container |
data-api-url | string | https://api.neuroon.ai | API URL |
data-refresh-endpoint | string | null | URL to automatically refresh token |
data-theme | string | "auto" | Theme: "light", "dark", "auto", "detect" |
data-locale | string | "es" | Language: "es", "en" |
data-display-mode | string | "fullscreen" | Mode: "fullscreen", "panel" |
data-placeholder | string | "" | Search input placeholder |
data-results-per-page | number | 20 | Products per page |
data-show-prices | boolean | true | Show prices |
data-show-brands | boolean | true | Show brands |
JavaScript configuration
For more control, use the JavaScript API:
const widget = NeuroonWidget.init({
container: '#neuroon-search',
token: 'YOUR_TOKEN',
apiUrl: 'https://api.neuroon.ai',
theme: 'auto',
locale: 'en',
features: {
suggestions: true,
filters: true,
voiceSearch: true,
imageSearch: true,
aiAssistant: false,
},
ui: {
placeholder: 'What are you looking for?',
resultsPerPage: 20,
showPrices: true,
showBrands: true,
layout: 'grid',
displayMode: 'fullscreen',
},
tracking: {
clicks: true,
conversions: false,
conversionSelector: '',
},
callbacks: {
onSearch: (query) => console.log('Search:', query),
onResultClick: (product) => console.log('Click:', product),
},
});
Features
Control which features are available in the widget.
interface FeatureFlags {
suggestions?: boolean; // Autocomplete (default: true)
filters?: boolean; // Filters panel (default: true)
voiceSearch?: boolean; // Voice search (default: true)
imageSearch?: boolean; // Image search (default: true)
aiAssistant?: boolean; // AI assistant with responses (default: false)
}
Voice search
features: {
voiceSearch: true, // Enabled by default
}
- Requires HTTPS (except localhost)
- Supported browsers: Chrome, Safari, Edge
- Languages: Spanish (es-ES), English (en-US)
Image search
features: {
imageSearch: true, // Enabled by default
}
- Supported formats: JPEG, PNG, WebP
- Maximum size: 5MB
- Allows camera capture or file upload
AI Assistant
features: {
aiAssistant: true, // Disabled by default
}
When active, the widget displays:
- Contextual AI assistant responses
- Guided filters with confidence scores
- Refined query suggestions
The AI assistant is disabled by default to optimize performance. Only enable it if your plan includes it.
Guided filters
Guided filters are automatically generated based on user search intent. They include:
- Relevant categories
- Suggested brands
- Price ranges
- Related tags
No additional configuration needed, just filters: true.
UI Options
Customize the widget interface.
interface UIOptions {
placeholder?: string; // Input placeholder
resultsPerPage?: number; // Products per page (default: 20)
showPrices?: boolean; // Show prices (default: true)
showBrands?: boolean; // Show brands (default: true)
layout?: 'grid' | 'list'; // Results layout (default: 'grid')
displayMode?: 'fullscreen' | 'panel'; // Display mode
}
Display Mode
| Mode | Description |
|---|---|
fullscreen | Full-screen modal (default) |
panel | Side panel (sidebar) |
ui: {
displayMode: 'panel', // Opens as side panel
}
Theme
The widget supports 4 theme modes:
| Value | Behavior |
|---|---|
light | Always light theme |
dark | Always dark theme |
auto | Follows system prefers-color-scheme |
detect | Auto-detects host site styles |
theme: 'detect', // Auto-detects your site colors
The detect mode analyzes your page styles (background colors, text, accents) and adapts the widget automatically. Ideal for integrations where you don't control the site theme.
Tracking
Configure widget event tracking.
interface TrackingConfig {
clicks?: boolean; // Product click tracking (default: true)
conversions?: boolean; // Conversion tracking (default: false)
conversionSelector?: string; // CSS selector for conversion buttons
}
Click tracking
Enabled by default. Records when a user clicks on a product.
Conversion tracking
tracking: {
conversions: true,
conversionSelector: '.add-to-cart-button', // CSS selector
}
When a user:
- Searches for a product in the widget
- Clicks on the result
- Clicks the button matching
conversionSelector
A conversion is recorded attributed to that search.
Token Refresh
The token is valid for 1 hour. For long sessions, configure a refresh endpoint.
Option 1: With data-attribute (recommended)
<script
src="https://cdn.neuroon.ai/widget.js"
data-token="YOUR_INITIAL_TOKEN"
data-refresh-endpoint="/api/neuroon/refresh-token"
data-container="#neuroon-search">
</script>
Option 2: With JavaScript
const widget = NeuroonWidget.init({
container: '#neuroon-search',
token: initialToken,
refreshEndpoint: '/api/neuroon/refresh-token',
});
The widget automatically:
- Detects when the token is about to expire (5 min before)
- Makes a
GETrequest to the configured endpoint - Expects response
{ "token": "new_token" } - Updates the token internally
Backend endpoint
Your endpoint should return JSON with the new token:
// Node.js / Express
app.get('/api/neuroon/refresh-token', (req, res) => {
if (!req.session.userId) {
return res.status(401).json({ error: 'Unauthorized' });
}
const token = generateWidgetToken(process.env.NEUROON_SHOP_API_KEY);
res.json({ token });
});
# Python / Flask
@app.route('/api/neuroon/refresh-token')
def refresh_token():
if not session.get('user_id'):
return jsonify(error='Unauthorized'), 401
token = generate_widget_token(os.environ['NEUROON_SHOP_API_KEY'])
return jsonify(token=token)
// PHP
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
$token = generateWidgetToken($_ENV['NEUROON_SHOP_API_KEY']);
echo json_encode(['token' => $token]);
Option 3: Custom callback
For cases with custom logic (special headers, auth tokens, etc.):
const widget = NeuroonWidget.init({
container: '#neuroon-search',
token: initialToken,
callbacks: {
onTokenExpiring: async () => {
const response = await fetch('/api/neuroon/refresh-token', {
headers: { 'Authorization': `Bearer ${myAuthToken}` }
});
const data = await response.json();
return data.token;
},
},
});
Without refresh configured
If you don't configure refresh:
- The token expires after 1 hour
- Subsequent searches will fail
- The user will need to reload the page
Always configure data-refresh-endpoint in applications where the user may stay on the page for more than 1 hour.
Complete configuration
const widget = NeuroonWidget.init({
// Required
container: '#neuroon-search',
token: 'YOUR_TOKEN',
// Optional
apiUrl: 'https://api.neuroon.ai',
refreshEndpoint: '/api/neuroon/refresh-token',
theme: 'auto',
locale: 'en',
// Features
features: {
suggestions: true,
filters: true,
voiceSearch: true,
imageSearch: true,
aiAssistant: false,
},
// UI
ui: {
placeholder: 'What are you looking for?',
resultsPerPage: 20,
showPrices: true,
showBrands: true,
layout: 'grid',
displayMode: 'fullscreen',
},
// Tracking
tracking: {
clicks: true,
conversions: false,
conversionSelector: '',
},
// Styles (see Theming)
styles: {
primary: '#06b6d4',
// ...more variables
},
// Translations (see Translations)
translations: {
// ...custom translations
},
// Callbacks
callbacks: {
onSearch: (query) => {},
onResultClick: (product) => {},
onFilterChange: (filters) => {},
onConversion: (product) => {},
onError: (error) => {},
onTokenExpiring: async () => {},
},
});
Next steps
- Theming - Customize colors and styles
- Translations - Customize texts
- JavaScript API - Programmatic control
- Callbacks - Respond to events