Skip to main content

Widget configuration

This page is the single source of truth for NeuroonWidgetConfig, verified line by line against the widget's source code (src/types.ts + src/context/ConfigContext.tsx) — not against any other page on this site. If another page (even the Snippet Builder) disagrees with what's stated here, this page is correct.

The widget accepts configuration through two paths:

  1. data-* attributes on the <script> for auto-init (server-rendered).
  2. NeuroonWidgetConfig via window.NeuroonWidget.init(config) for programmatic control.

Both paths produce the same instance. If you pass both, init(config) takes precedence.

data-* attributes

AttributeRequiredDefaultWhat it does
data-tokenyesWidget Token signed by your server
data-containerno#neuroon-searchCSS selector for the container. If it matches no element, auto-init aborts with a console warning
data-themenoautolight, dark, auto
data-localenoautodetect (fallback es)es, en, fr, de, it, pt, ca, eu, gl
data-api-urlnohttps://api.neuroon.aiAPI host override. Available since v0.9.19 — in earlier versions this attribute was silently ignored and apiUrl was only reachable via init()
data-placeholderno""Empty-input text
data-suggestionsnotrue"false" disables suggestions
data-filtersnotrue"false" disables filters
data-primary-colornoDoes nothing. It exists in the parser and validates the color format, but the CSS mapping is empty — it paints no visual override. Use styles.primary via init() instead

These are the only attributes the widget reads from the <script> tag — any other data-* gets forwarded onto the tag but is silently ignored. For translations, cart, tracking, callbacks, monitoring or refreshEndpoint, use programmatic init().

NeuroonWidgetConfig

interface NeuroonWidgetConfig {
container: string | HTMLElement
token: string
apiUrl?: string // default: 'https://api.neuroon.ai'
fallbackApiUrl?: string // optional — secondary API host if the search against apiUrl fails (since v0.9.23)
refreshEndpoint?: string // URL to refresh the token; see note below
theme?: 'auto' | 'light' | 'dark' | 'detect' // default: 'auto'
locale?: 'es' | 'en' | 'fr' | 'de' | 'it' | 'pt' | 'ca' | 'eu' | 'gl'
translations?: Partial<Translations>
styles?: StyleOverrides | { light?: StyleOverrides; dark?: StyleOverrides }
features?: FeatureFlags
ui?: UIOptions
tracking?: TrackingConfig
callbacks?: Callbacks
monitoring?: MonitoringConfig
cart?: CartConfig
}

FeatureFlags

interface FeatureFlags {
suggestions?: boolean // default: true — suggestions dropdown
filters?: boolean // default: true — guided filters
voiceSearch?: boolean // default: true — voice search (requires browser support)
imageSearch?: boolean // default: true — image/visual search
aiAssistant?: boolean // default: true — conversational assistant
comparison?: boolean // default: true — product comparator (max 4)
mentions?: boolean // default: true — @mentions and drag&drop of products in chat
streaming?: boolean // default: true — token-by-token streaming of agent responses
agentSearch?: boolean // default: true — conversational/agentic search mode
fastSearch?: boolean // default: false — instant, non-conversational search mode (since v0.9.19)
}

UIOptions

interface UIOptions {
placeholder?: string // default: '' — empty-input text
resultsPerPage?: number // default: 20 — results per page
showPrices?: boolean // default: true — show prices
showBrands?: boolean // default: true — show brands
layout?: 'grid' | 'list' // default: 'grid' — ⚠️ has no effect (see note)
displayMode?: 'fullscreen' | 'panel' // default: 'fullscreen'
fabPosition?: string // default: 'bottom-right' — floating action button position
fabHint?: string // default: '' — FAB tooltip text
overlayContainer?: HTMLElement | null // default: null — confines the overlay to this element (since v0.9.26)
}

callbacks

interface Callbacks {
onSearch?: (query: string) => void
onResultClick?: (product: Product) => void
onFilterChange?: (filters: AppliedFilters) => void
onError?: (error: Error) => void
onTokenExpiring?: () => Promise<string>
onTokenRefreshed?: (newToken: string) => void
}

All 6 fields are genuinely wired (verified in App.tsx, useSearch.ts, useProductHandlers.ts, useSearchHandlers.ts). There's also an onConversion?: (product: Product) => void field on the type, but it is not wired to anything — real conversion attribution goes through the neuroon_clicks cookie, not this callback.

TrackingConfig

interface TrackingConfig {
clicks?: boolean // default: true — tracks product clicks (real)
}

clicks fires POST /api/widget/track/click on every click/add-to-cart of a product, and controls whether the neuroon_clicks attribution cookie gets written — read by the WordPress plugin when an order completes. The onConversion callback (see above) is still not wired to anything — real attribution always goes through this cookie, not that callback.

monitoring (optional)

interface MonitoringConfig {
applicationId: string
clientToken: string
// …Datadog RUM SDK options
}

If configured, the widget asynchronously initializes @datadog/browser-rum-slim — Datadog's auto-instrumented RUM (resources, interactions, long tasks) genuinely works. The widget's custom tracking hooks (trackAction/trackError) exist in the code but no component calls them today — don't expect your own custom events in your Datadog dashboard, only what Datadog captures automatically.

cart

See Cart integration for the full CartConfig, CartState and CartOperationResult contract.

styles

Accepts a flat object (same values for both themes) or one per theme ({ light: {...}, dark: {...} }). See Theming and CSS Variables for the full field list.

Validation

RuleMessage
token missing[NeuroonWidget] token is required
container missing[NeuroonWidget] container is required
apiUrl is not a valid URL[NeuroonWidget] Invalid apiUrl
theme not supportedwarning, fallback to auto
locale not supportedwarning, fallback to es
resultsPerPage <= 0[NeuroonWidget] resultsPerPage must be greater than 0

Further reading