Finder-v2 Widget Documentation
π Table of Contents
π Overview
The Finder-v2 widget is a modern, Vue 3-based vehicle wheel/tire finder widget that provides a seamless integration experience for client websites. It features a powerful event system, customizable templates, and a flexible color system.
- β Vue 3 Composition API architecture
- β TailwindCSS v4 styling system
- β Cross-origin communication via postMessage
- β Customizable templates with Django-like syntax
- β Dynamic color theming system
π― Event System
The Finder-v2 widget implements a comprehensive event system that maintains full compatibility with the legacy
WheelSizeWidgets JavaScript API while leveraging modern Vue 3 patterns.
Event Types
| Event Name | Description | When Fired | Payload |
|---|---|---|---|
ready:document |
DOM is ready | When widget DOM is fully loaded | Context object |
ready:window |
Window and data loaded | After window load AND initial data load complete | Context object |
change:year |
Year selection changed | When user selects a year | { value: { slug, title } } |
change:make |
Make selection changed | When user selects a make | { value: { slug, title } } |
change:model |
Model selection changed | When user selects a model | { value: { slug, title } } |
change:generation |
Generation selection changed | When user selects a generation | { value: { slug, title } } |
change:modification |
Modification selection changed | When user selects a modification | { value: { slug, title } } |
search:start |
Search initiated | Before searchByVehicle() call |
Context with selections |
search:complete |
Search completed | After results loaded | Includes counts and timings |
search:error |
Search failed | On search error | { error_message: string } |
results:display |
Results rendered | After DOM renders results | See detailed structure below |
Event Payload Structure
All events are sent with a standardized envelope structure via window.parent.postMessage:
{
"src": "<child iframe url>",
"type": "<event type>",
"data": {
"context": {
"config": {},
"widgetUuid": "<uuid>",
"widgetType": "finder-v2",
"flowType": "primary|alternative|year_select",
"selections": {
"year": "<slug>",
"make": "<slug>",
"model": "<slug>",
"generation": "<slug>",
"modification": "<slug>"
}
}
}
}
Special Event: results:display
The results:display event is fired after search results are rendered in the widget's DOM:
{
"type": "results:display",
"data": {
"results_count": 3,
"context": {
"config": { /* widget configuration */ },
"widgetUuid": "...",
"widgetType": "finder-v2",
"flowType": "primary|alternative|year_select",
"selections": {
"year": "<slug>",
"make": "<slug>",
"model": "<slug>",
"generation": "<slug>",
"modification": "<slug>"
}
}
}
}
results:display event does NOT include full results data to keep messages lightweight.
Results are rendered inside the widget. Parent pages can use results_count and context for analytics.
Parent Page Integration
Here's how to integrate the event system in your parent page:
<script src="//services.wheel-size.com/static/widget/code/local/ws-widget.js"></script>
<script>
// Create widget instance
var widget = WheelSizeWidgets.create('#ws-widget', {
uuid: 'your-uuid',
type: 'finder-v2'
});
// Listen to events
widget.on('ready:window', function(e) {
console.log('Widget ready', e);
});
widget.on('change:make', function(e) {
console.log('Make selected:', e.data.value);
// e.data.value = { slug: 'toyota', title: 'Toyota' }
});
widget.on('search:start', function(e) {
console.log('Search started with selections:', e.data.context.selections);
});
widget.on('search:complete', function(e) {
console.log('Search completed');
});
widget.on('search:error', function(e) {
console.error('Search failed:', e.data.error_message);
});
widget.on('results:display', function(e) {
console.log('Results displayed. Count:', e.data.results_count);
console.log('Vehicle:', e.data.context.selections);
});
</script>
π Template System
The Finder-v2 widget uses a Django-like template syntax that allows for powerful customization of the results display. Templates can access all data returned from the Finder API and use various control structures.
Template Syntax
| Syntax Type | Pattern | Example | Description |
|---|---|---|---|
| Variables | {{ variable }} |
{{ make.name }} |
Output variable value |
| Nested Access | {{ parent.child }} |
{{ engine.power.hp }} |
Access nested properties |
| Ternary | {{ condition ? true : false }} |
{{ wheel.is_stock ? "OE" : "AM" }} |
Inline conditional output |
| If Statement | {% if condition %}...{% endif %} |
{% if wheel.is_stock %}OE{% endif %} |
Conditional block |
| If-Else | {% if condition %}...{% else %}...{% endif %} |
{% if wheel.rear.tire %}Dual{% else %}Single{% endif %} |
Conditional with fallback |
| If-Elif-Else | {% if cond1 %}...{% elif cond2 %}...{% else %}...{% endif %} |
{% if hp > 300 %}High{% elif hp > 200 %}Med{% else %}Low{% endif %} |
Multiple conditions |
| Negation | {% if not condition %}...{% endif %} |
{% if not wheel.showing_fp_only %}...{% endif %} |
Negated condition |
| Comparison | {% if value == "text" %}...{% endif %} |
{% if wheel.front.rim_diameter > 18 %}Large{% endif %} |
Operators: ==, !=, >, <, >=, <= |
| For Loop | {% for item in array %}...{% endfor %} |
{% for wheel in wheels %}...{% endfor %} |
Iterate over array |
Loop Counter Variables
When inside a {% for %} loop, the following special variables are available:
| Variable | Type | Description | Example Values |
|---|---|---|---|
{{ loop.index }} |
number | Current iteration (1-based) | 1, 2, 3... |
{{ loop.index0 }} |
number | Current iteration (0-based) | 0, 1, 2... |
{{ loop.first }} |
boolean | True for first iteration | true / false |
{{ loop.last }} |
boolean | True for last iteration | true / false |
{{ loop.length }} |
number | Total number of items | 3, 10, 25... |
π‘ Pro Tip: Clean URL Parameters
Use loop counters to create clean URLs without trailing ampersands:
{% for wheel in wheels %}{% if not loop.first %}&{% endif %}param={{ wheel.rim }}{% endfor %}
This produces: param=value1¶m=value2¶m=value3
Important: Always use & instead of bare & to avoid HTML entity conversion issues (like ¶ becoming ΒΆ).
Comparison Operators (NEW! β¨)
The template engine now supports full comparison operators for advanced conditional logic:
| Operator | Description | String Example | Numeric Example |
|---|---|---|---|
== |
Equal to | {% if engine.fuel == "Electric" %} |
{% if wheel.front.rim_diameter == 18 %} |
!= |
Not equal to | {% if engine.fuel != "Gasoline" %} |
{% if wheel.front.rim_diameter != 17 %} |
> |
Greater than | - | {% if engine.power.hp > 300 %} |
< |
Less than | - | {% if wheel.front.rim_diameter < 18 %} |
>= |
Greater or equal | - | {% if engine.power.hp >= 200 %} |
<= |
Less or equal | - | {% if wheel.front.rim_diameter <= 19 %} |
- Nested ternary NOT supported: Don't use
{{ a ? "x" : (b ? "y" : "z") }} - Use {% elif %} instead: For multiple conditions, always use
{% if %}...{% elif %}...{% endif %} - No logical operators:
and,orare not supported. Use nested{% if %}blocks. - No substring matching: The
inoperator is not available. Use exact string comparison. - Multiline variables OK: Variables can span multiple lines for readability.
Template Filters (NEW! β¨)
Transform variable values using filters with the pipe (|) syntax. Filters can be chained together.
| Filter | Description | Syntax | Example |
|---|---|---|---|
dashify |
Replace spaces with dashes | {{ variable | dashify }} |
"M14 x 1.5" β "M14-x-1.5" |
replace |
Replace characters | {{ variable | replace:"old":"new" }} |
"hello world" β "hello-world" |
upper |
Convert to UPPERCASE | {{ variable | upper }} |
"toyota" β "TOYOTA" |
lower |
Convert to lowercase | {{ variable | lower }} |
"TOYOTA" β "toyota" |
trim |
Remove leading/trailing whitespace | {{ variable | trim }} |
" text " β "text" |
default |
Use fallback if value is empty | {{ variable | default:"N/A" }} |
"" β "N/A" |
urlencode |
URL encode for href attributes | {{ variable | urlencode }} |
"hello world" β "hello%20world" |
π‘ Filter Usage Examples
Format thread size for URL:
Converts "M14 x 1.5" β "M14-x-1.5" in the URL
Chain multiple filters:
{{ make.name | upper | trim }}
Applies both uppercase conversion and whitespace trimming
Provide fallback for empty values:
{{ technical.centre_bore | default:"Unknown" }}
Available Template Variables
The following variables are available in templates based on the Finder API v2 response:
Vehicle Information
| Variable Path | Type | Description | Example Value |
|---|---|---|---|
make.name |
string | Make/brand name | "Toyota" |
make.slug |
string | Make identifier | "toyota" |
model.name |
string | Model name | "Camry" |
model.slug |
string | Model identifier | "camry" |
generation.name |
string | Generation name | "XV70" |
generation.start |
number | Generation start year | 2017 |
generation.end |
number | Generation end year | 2024 |
generation.platform |
string | Platform code | "GA-K" |
generation.bodies |
array | Body types | ["Sedan", "Wagon"] |
vehicle.image |
string | Vehicle image URL Paid Only | "https://cdn.wheel-size.com/automobile/body/..." |
start_year |
number | Production start year | 2018 |
end_year |
number | Production end year | 2024 |
name |
string | Modification/trim name | "GLE 53 4Matic+ (5AA-167161)" |
trim |
string | Short modification/trim name | "GLE 53 4Matic+" |
body |
string | Body code (Japan) | "5AA-167161" |
Engine Information
| Variable Path | Type | Description | Example Value |
|---|---|---|---|
engine.fuel |
string | Fuel type | "Gasoline" |
engine.capacity |
string | Engine displacement | "2.5" |
engine.type |
string | Engine type | "I4" |
engine.code |
string | Engine code | "A25A-FKS" |
engine.power.hp |
number | Power in HP | 203 |
engine.power.PS |
number | Power in PS | 206 |
engine.power.kW |
number | Power in kW | 151 |
Wheel/Tire Information (in wheels array)
| Variable Path | Type | Description | Example Value |
|---|---|---|---|
wheel.is_stock |
boolean | OE fitment flag | true |
wheel.is_recommended_for_winter |
boolean | Winter recommendation | false |
wheel.is_runflat_tires |
boolean | Run-flat tires | false |
wheel.is_extra_load_tires |
boolean | Extra load rating | false |
wheel.is_pressed_steel_rims |
boolean | Steel wheels | false |
wheel.showing_fp_only |
boolean | Front pair only | false |
wheel.front.tire |
string | Front tire size | "215/55R17" |
wheel.front.tire_full |
string | Full tire spec | "215/55R17 94V" |
wheel.front.rim |
string | Front rim size | "7Jx17 ET45" |
wheel.front.rim_diameter |
string | Rim diameter | "17" |
wheel.front.rim_width |
string | Rim width | "7" |
wheel.front.rim_offset |
string | Rim offset | "45" |
wheel.front.tire_pressure.bar |
number | Pressure in bar | 2.3 |
wheel.front.tire_pressure.psi |
number | Pressure in PSI | 33 |
wheel.rear.* |
various | Rear specs (same structure as front) | - |
Note: Rear wheel data is only available when different from front specs. When front and rear are identical, check wheel.showing_fp_only and use front values for both axles.
Technical Specifications
| Variable Path | Type | Description | Example Value |
|---|---|---|---|
technical.bolt_pattern |
string | Bolt pattern | "5x114.3" |
technical.stud_holes |
number | Number of studs | 5 |
technical.pcd |
string | Pitch circle diameter | "114.3" |
technical.centre_bore |
string | Center bore diameter | "60.1" |
technical.wheel_fasteners.type |
string | Fastener type | "Lug bolts" |
technical.wheel_fasteners.thread_size |
string | Thread specifications | "M15 x 1.25" |
technical.wheel_tightening_torque |
string/null | Torque specification | "88 - 108 Nm" |
regions |
array | Market regions | ["USDM", "CDM"] |
Template Examples
Wheel Size Filtering and Categorization
<!-- Show only large wheels (18" and up) -->
{% for wheel in wheels %}
{% if wheel.front.rim_diameter >= 18 %}
<div class="large-wheel-option">
<span class="text-orange-500 font-bold">π₯ Large Wheels!</span>
{{ wheel.front.rim_diameter }}" - {{ wheel.front.tire }}
</div>
{% endif %}
{% endfor %}
<!-- Categorize by wheel size -->
{% for wheel in wheels %}
<div class="wheel-card">
{% if wheel.front.rim_diameter >= 20 %}
<span class="badge bg-red-500 text-white">Extra Large (20"+)</span>
{% elif wheel.front.rim_diameter >= 18 %}
<span class="badge bg-orange-500 text-white">Large (18-19")</span>
{% elif wheel.front.rim_diameter >= 17 %}
<span class="badge bg-blue-500 text-white">Standard (17")</span>
{% else %}
<span class="badge bg-gray-500 text-white">Compact (<17")</span>
{% endif %}
<div>{{ wheel.front.tire }} - {{ wheel.front.rim }}</div>
</div>
{% endfor %}
Engine Power Classification
<div class="engine-info">
<h4>{{ engine.type }} {{ engine.capacity }}L</h4>
<!-- Power category badge -->
{% if engine.power.hp > 300 %}
<span class="badge bg-red-500 text-white">β‘ High Performance ({{ engine.power.hp }} hp)</span>
{% elif engine.power.hp > 200 %}
<span class="badge bg-orange-500 text-white">ποΈ Performance ({{ engine.power.hp }} hp)</span>
{% elif engine.power.hp > 150 %}
<span class="badge bg-blue-500 text-white">π Standard ({{ engine.power.hp }} hp)</span>
{% else %}
<span class="badge bg-gray-500 text-white">π΅ Economy ({{ engine.power.hp }} hp)</span>
{% endif %}
<!-- Fuel type with icons -->
<div class="fuel-type">
{% if engine.fuel == "Electric" %}
β‘ Electric Vehicle
{% elif engine.fuel == "Hybrid" %}
π Hybrid Engine
{% elif engine.fuel == "Diesel" %}
π’οΈ Diesel Engine
{% else %}
β½ Gasoline Engine
{% endif %}
</div>
</div>
Translation: Fastener Types (Localization Example)
<div class="technical-specs">
<h4>Technical Specifications</h4>
<!-- Translate fastener type to local language -->
<div class="spec-row">
<span class="spec-label">
{% if technical.wheel_fasteners.type == "Lug bolts" %}
SkrΕ«ves: <!-- Latvian translation -->
{% elif technical.wheel_fasteners.type == "Lug nuts" %}
UzgrieΕΎΕi: <!-- Latvian translation -->
{% else %}
{{ technical.wheel_fasteners.type }}:
{% endif %}
</span>
<span class="spec-value">
{{ technical.stud_holes }} Γ {{ technical.wheel_fasteners.thread_size }}
</span>
</div>
<div class="spec-row">
<span class="spec-label">SkrΕ«vju solis:</span> <!-- Bolt Pattern in Latvian -->
<span class="spec-value">{{ technical.bolt_pattern }}</span>
</div>
<div class="spec-row">
<span class="spec-label">CentrΔlΔ atvere:</span> <!-- Center Bore in Latvian -->
<span class="spec-value">{{ technical.centre_bore }} mm</span>
</div>
</div>
Staggered vs Non-Staggered Setup Detection
{% for wheel in wheels %}
<div class="fitment-card">
<!-- Compare front and rear diameters -->
{% if wheel.front.rim_diameter == wheel.rear.rim_diameter %}
<span class="badge bg-blue-500 text-white">β Non-Staggered Setup</span>
<div>Front & Rear: {{ wheel.front.tire }} - {{ wheel.front.rim }}</div>
{% else %}
<span class="badge bg-purple-500 text-white">β‘ Staggered Setup</span>
<div>Front: {{ wheel.front.tire }} - {{ wheel.front.rim }}</div>
{% if wheel.rear.tire %}
<div>Rear: {{ wheel.rear.tire }} - {{ wheel.rear.rim }}</div>
{% endif %}
{% endif %}
</div>
{% endfor %}
Conditional Styling Based on Values
{% for wheel in wheels %}
<!-- Dynamic background color based on diameter -->
<div class="
{% if wheel.front.rim_diameter > 19 %}bg-red-100 border-red-500
{% elif wheel.front.rim_diameter > 17 %}bg-orange-100 border-orange-500
{% else %}bg-blue-100 border-blue-500
{% endif %}
border-2 p-4 rounded-lg">
<!-- Dynamic text color based on stock status -->
<h3 class="{% if wheel.is_stock %}text-primary-color{% else %}text-secondary-color{% endif %} font-bold">
{{ wheel.is_stock ? "Original Equipment" : "Aftermarket Option" }}
</h3>
<div>{{ wheel.front.tire }} - {{ wheel.front.rim }}</div>
<!-- Show premium badge for larger wheels -->
{% if wheel.front.rim_diameter >= 19 %}
<div class="mt-2 text-sm text-orange-600 font-semibold">
π Premium Size Upgrade
</div>
{% endif %}
</div>
{% endfor %}
Basic Vehicle Information
<h3>{{ make.name }} {{ model.name }} ({{ start_year }}-{{ end_year }})</h3>
{% if generation.name %}
<p>Generation: {{ generation.name }}</p>
{% endif %}
Engine Details with Conditionals
{% if engine.type %}
<div class="engine-info">
<span>{{ engine.type }} {{ engine.capacity }}L</span>
{% if engine.power.hp %}
<span>β’ {{ engine.power.hp }} hp</span>
{% endif %}
{% if engine.fuel %}
<span>β’ {{ engine.fuel }}</span>
{% endif %}
</div>
{% endif %}
Wheel Fitments with Loops and Ternary
<div class="fitments">
{% for wheel in wheels %}
<div class="fitment-card">
<span class="badge">{{ wheel.is_stock ? "OE" : "Aftermarket" }}</span>
<div class="specs">
<div>Front: {{ wheel.front.tire }} on {{ wheel.front.rim }}</div>
{% if not wheel.showing_fp_only %}
{% if wheel.rear.tire %}
<div>Rear: {{ wheel.rear.tire }} on {{ wheel.rear.rim }}</div>
{% endif %}
{% endif %}
{% if wheel.front.tire_pressure.bar %}
<div>Pressure: {{ wheel.front.tire_pressure.bar }} bar / {{ wheel.front.tire_pressure.psi }} psi</div>
{% endif %}
</div>
{% if wheel.is_recommended_for_winter %}
<span class="winter-badge">βοΈ Winter Recommended</span>
{% endif %}
</div>
{% endfor %}
</div>
Using Loop Counters for Clean Output
<!-- Numbered list of wheels -->
{% for wheel in wheels %}
<div>{{ loop.index }}. {{ wheel.front.rim }} - {{ wheel.front.tire }}</div>
{% endfor %}
<!-- Comma-separated list -->
Available sizes: {% for wheel in wheels %}{{ wheel.front.rim }}{% if not loop.last %}, {% endif %}{% endfor %}
<!-- Show progress indicator -->
{% for wheel in wheels %}
<div class="wheel-option">
<span>Option {{ loop.index }} of {{ loop.length }}</span>
<span>{{ wheel.front.rim }}</span>
</div>
{% endfor %}
<!-- Clean URL parameters without trailing ampersand -->
<a href="http://example.com/search?{% for wheel in wheels %}{% if not loop.first %}&{% endif %}size={{ wheel.front.rim }}{% endfor %}">
Search compatible wheels
</a>
Vehicle Image Display (Paid Widgets, Alternative Flow)
<div class="vehicle-result">
<h3>{{ make.name }} {{ model.name }} ({{ start_year }}-{{ end_year }})</h3>
{% if vehicle.image %}
<div class="vehicle-image-container">
<img src="{{ vehicle.image }}"
alt="{{ make.name }} {{ model.name }}"
style="max-width: 100%; height: auto; border-radius: 8px;">
<p class="image-caption">{{ generation.name }}</p>
</div>
{% else %}
<div class="no-image-placeholder">
<p>Vehicle image not available</p>
</div>
{% endif %}
<!-- Wheel fitment data with numbering -->
{% for wheel in wheels %}
<div class="wheel-option">
<strong>{{ loop.index }}. {{ wheel.is_stock ? 'OE' : 'Aftermarket' }}:</strong>
{{ wheel.front.tire }} - {{ wheel.front.rim }}
{% if loop.first %}<span class="badge">Primary</span>{% endif %}
</div>
{% endfor %}
</div>
vehicle.image placeholder is only available for:
- Paid widgets (subscriptionPaid: true)
- Alternative flow (not available in Primary or Year-first flows)
- The image URL is extracted from the generation API response
Complete Template Example
<div class="ws-results">
<header class="vehicle-header">
<h2>{{ make.name }} {{ model.name }}</h2>
<div class="vehicle-details">
<span>{{ start_year }}-{{ end_year }}</span>
{% if generation.name %}
<span>β’ {{ generation.name }}</span>
{% endif %}
{% if trim %}
<span>β’ {{ trim }}</span>
{% endif %}
</div>
{% if engine.type %}
<div class="engine-specs">
{{ engine.capacity }}L {{ engine.type }}
{% if engine.power.hp %}
({{ engine.power.hp }} hp)
{% endif %}
</div>
{% endif %}
</header>
<div class="technical-info">
{% if technical.bolt_pattern %}
<div>Bolt Pattern: {{ technical.bolt_pattern }}</div>
{% endif %}
{% if technical.centre_bore %}
<div>Center Bore: {{ technical.centre_bore }} mm</div>
{% endif %}
</div>
<div class="wheel-options">
<h3>Wheel & Tire Options</h3>
{% for wheel in wheels %}
<div class="option-card {{ wheel.is_stock ? 'oe-option' : 'aftermarket-option' }}">
<div class="option-header">
<span class="option-type">
{{ wheel.is_stock ? "Original Equipment" : "Aftermarket Option" }}
</span>
<span class="wheel-size">{{ wheel.front.rim_diameter }}" wheels</span>
</div>
<div class="fitment-details">
<div class="front-fitment">
<strong>Front:</strong>
<div>Tire: {{ wheel.front.tire_full }}</div>
<div>Rim: {{ wheel.front.rim }}</div>
{% if wheel.front.tire_pressure.bar %}
<div>Pressure: {{ wheel.front.tire_pressure.bar }} bar</div>
{% endif %}
</div>
{% if not wheel.showing_fp_only %}
{% if wheel.rear.tire %}
<div class="rear-fitment">
<strong>Rear:</strong>
<div>Tire: {{ wheel.rear.tire_full }}</div>
<div>Rim: {{ wheel.rear.rim }}</div>
{% if wheel.rear.tire_pressure.bar %}
<div>Pressure: {{ wheel.rear.tire_pressure.bar }} bar</div>
{% endif %}
</div>
{% endif %}
{% endif %}
</div>
<div class="fitment-flags">
{% if wheel.is_recommended_for_winter %}
<span class="flag winter">βοΈ Winter</span>
{% endif %}
{% if wheel.is_runflat_tires %}
<span class="flag runflat">π‘οΈ Run-flat</span>
{% endif %}
{% if wheel.is_extra_load_tires %}
<span class="flag xl">πͺ XL</span>
{% endif %}
{% if wheel.is_pressed_steel_rims %}
<span class="flag steel">π§ Steel</span>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
π¨ Color System
The Finder-v2 widget implements a flexible color theming system that allows customization to match your brand. The system uses CSS custom properties that can be overridden while maintaining consistent naming conventions.
Primary Brand Color Classes
The primary brand color is the main accent color used throughout the widget for interactive elements, highlights, and brand-specific styling. These classes adapt to your configured primary color.
| CSS Class | Purpose | Usage Example |
|---|---|---|
text-primary-color |
Primary color text | Links, important labels, OE badges |
bg-primary-color |
Primary color background | Buttons, selected states, badges |
border-primary-color |
Primary color border | Active inputs, highlighted cards |
hover:bg-primary-color |
Primary hover background | Button hover states |
hover:text-primary-color |
Primary hover text | Link hover states |
hover:border-primary-color |
Primary hover border | Card hover states |
Opacity Variants
Use opacity modifiers for subtle backgrounds and overlays:
| CSS Class | Opacity | Use Case |
|---|---|---|
bg-primary-color/5 |
5% | Very subtle background tint |
bg-primary-color/10 |
10% | Light background for OE options |
bg-primary-color/20 |
20% | Badge backgrounds, hover states |
bg-primary-color/50 |
50% | Overlays, disabled states |
Additional Color Classes
| CSS Class | Purpose | Typical Use |
|---|---|---|
text-main-color |
Main text color | Body text, headings |
text-secondary-color |
Secondary text | Labels, descriptions, muted text |
bg-background-color |
Background color | Card backgrounds, containers |
border-secondary-color |
Secondary borders | Dividers, neutral borders |
text-accent-color |
Accent color text | Alternative highlights |
bg-accent-color |
Accent backgrounds | Aftermarket badges |
Usage Examples
OE vs Aftermarket Distinction
<!-- OE Option with primary color -->
<div class="border border-primary-color bg-primary-color/10 p-4 rounded">
<span class="text-primary-color font-semibold">Original Equipment</span>
<!-- content -->
</div>
<!-- Aftermarket Option with secondary color -->
<div class="border border-secondary-color hover:bg-secondary-color/10 p-4 rounded">
<span class="text-secondary-color font-semibold">Aftermarket</span>
<!-- content -->
</div>
Interactive Elements
<!-- Primary button -->
<button class="bg-primary-color text-white hover:bg-primary-color/90 px-4 py-2 rounded">
Search
</button>
<!-- Secondary button -->
<button class="border border-primary-color text-primary-color hover:bg-primary-color/10 px-4 py-2 rounded">
Clear
</button>
<!-- Link with primary color -->
<a href="#" class="text-primary-color hover:text-primary-color/80 underline">
View Details
</a>
Badges and Labels
<!-- OE Badge -->
<span class="inline-flex px-2 py-1 text-xs font-medium rounded-full bg-primary-color/20 text-primary-color">
OE
</span>
<!-- Aftermarket Badge -->
<span class="inline-flex px-2 py-1 text-xs font-medium rounded-full bg-secondary-color/20 text-secondary-color">
AM
</span>
<!-- Feature Badge -->
<span class="inline-flex px-2 py-1 text-xs font-medium rounded-full bg-accent-color/20 text-accent-color">
Winter
</span>
Cards with Hover Effects
<div class="bg-background-color border border-secondary-color hover:border-primary-color hover:shadow-lg transition-all duration-300 p-4 rounded-lg">
<h3 class="text-main-color font-semibold">17" Wheel Option</h3>
<p class="text-secondary-color">215/55R17 - 7Jx17 ET45</p>
<div class="mt-2">
<span class="text-primary-color font-medium">View Details β</span>
</div>
</div>
Complete Color System Example
<div class="widget-container">
<!-- Header with primary accent -->
<header class="border-b-2 border-primary-color pb-4 mb-6">
<h1 class="text-2xl font-bold text-main-color">Wheel Finder Results</h1>
<p class="text-secondary-color">Found 3 options for your vehicle</p>
</header>
<!-- Results grid -->
<div class="grid gap-4">
<!-- OE Option Card -->
<div class="bg-primary-color/5 border-2 border-primary-color rounded-lg p-6">
<div class="flex justify-between items-start mb-4">
<h3 class="text-lg font-semibold text-main-color">Factory Standard</h3>
<span class="bg-primary-color text-white px-3 py-1 rounded-full text-sm font-medium">
OE
</span>
</div>
<div class="space-y-2">
<div class="flex justify-between">
<span class="text-secondary-color">Tire:</span>
<span class="text-main-color font-medium">215/55R17</span>
</div>
<div class="flex justify-between">
<span class="text-secondary-color">Rim:</span>
<span class="text-main-color font-medium">7Jx17 ET45</span>
</div>
</div>
<button class="mt-4 w-full bg-primary-color hover:bg-primary-color/90 text-white py-2 rounded-lg transition-colors">
Select This Option
</button>
</div>
<!-- Aftermarket Option Card -->
<div class="bg-background-color border border-secondary-color hover:border-primary-color rounded-lg p-6 transition-colors">
<div class="flex justify-between items-start mb-4">
<h3 class="text-lg font-semibold text-main-color">Performance Upgrade</h3>
<span class="bg-accent-color/20 text-accent-color px-3 py-1 rounded-full text-sm font-medium">
AM
</span>
</div>
<div class="space-y-2">
<div class="flex justify-between">
<span class="text-secondary-color">Tire:</span>
<span class="text-main-color font-medium">225/50R18</span>
</div>
<div class="flex justify-between">
<span class="text-secondary-color">Rim:</span>
<span class="text-main-color font-medium">8Jx18 ET40</span>
</div>
</div>
<button class="mt-4 w-full border border-primary-color text-primary-color hover:bg-primary-color/10 py-2 rounded-lg transition-colors">
View Details
</button>
</div>
</div>
</div>
π API Reference
Widget Creation
// Basic widget creation
var widget = WheelSizeWidgets.create('#container-id', {
uuid: 'your-widget-uuid',
type: 'finder-v2',
// Optional configuration
config: {
theme: 'light',
language: 'en',
// ... other config options
}
});
// Alternative: Use existing iframe
var widget = WheelSizeWidgets.create('#existing-iframe-id');
Event Handling Methods
// Subscribe to an event
widget.on('event-name', function(eventData) {
console.log('Event received:', eventData);
});
// Unsubscribe from an event
widget.off('event-name', callbackFunction);
// One-time event listener
widget.once('ready:window', function(eventData) {
console.log('Widget is ready (fires once)');
});
Widget Methods
| Method | Parameters | Description | Returns |
|---|---|---|---|
create |
selector, config | Create widget instance | Widget instance |
on |
event, callback | Add event listener | void |
off |
event, callback | Remove event listener | void |
once |
event, callback | One-time event listener | void |
destroy |
- | Destroy widget instance | void |
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
uuid |
string | required | Widget UUID from admin panel |
type |
string | "finder-v2" | Widget type identifier |
language |
string | "en" | Widget language (en, de, fr, etc.) |
theme |
string | "light" | Color theme (light, dark, custom) |
flowType |
string | "primary" | Search flow (primary, alternative, year_select) |
π‘ Complete Integration Examples
Basic Integration
<!DOCTYPE html>
<html>
<head>
<title>Finder-v2 Widget Integration</title>
</head>
<body>
<!-- Widget container -->
<div id="wheel-finder"></div>
<!-- Load widget API -->
<script src="//services.wheel-size.com/static/widget/code/local/ws-widget.js"></script>
<script>
// Create widget when DOM is ready
document.addEventListener('DOMContentLoaded', function() {
var widget = WheelSizeWidgets.create('#wheel-finder', {
uuid: 'your-widget-uuid',
type: 'finder-v2'
});
// Listen for widget ready
widget.on('ready:window', function() {
console.log('Widget is ready for interaction');
});
// Track user selections
widget.on('change:make', function(e) {
console.log('User selected make:', e.data.value.title);
});
widget.on('change:model', function(e) {
console.log('User selected model:', e.data.value.title);
});
// Handle search results
widget.on('results:display', function(e) {
console.log('Results displayed:', e.data.results_count);
// Send to analytics, update page, etc.
});
});
</script>
</body>
</html>
Advanced Integration with Analytics
<script>
document.addEventListener('DOMContentLoaded', function() {
var widget = WheelSizeWidgets.create('#wheel-finder', {
uuid: 'your-widget-uuid',
type: 'finder-v2',
language: 'en',
theme: 'light'
});
// Analytics tracking
function trackEvent(action, label, value) {
if (typeof gtag !== 'undefined') {
gtag('event', action, {
'event_category': 'WheelFinder',
'event_label': label,
'value': value
});
}
}
// Track widget initialization
widget.on('ready:window', function() {
trackEvent('widget_loaded', 'finder-v2', 1);
});
// Track user journey
var selectionPath = [];
['year', 'make', 'model', 'generation', 'modification'].forEach(function(field) {
widget.on('change:' + field, function(e) {
selectionPath.push({
field: field,
value: e.data.value.slug,
title: e.data.value.title
});
trackEvent('selection_made', field, selectionPath.length);
});
});
// Track search events
widget.on('search:start', function(e) {
trackEvent('search_initiated', 'vehicle_search', 1);
console.log('Search path:', selectionPath);
});
widget.on('search:complete', function(e) {
trackEvent('search_completed', 'success', 1);
});
widget.on('search:error', function(e) {
trackEvent('search_failed', e.data.error_message, 0);
console.error('Search error:', e.data.error_message);
});
// Track results interaction
widget.on('results:display', function(e) {
var vehicle = e.data.context.selections;
var vehicleString = [
vehicle.year,
vehicle.make,
vehicle.model,
vehicle.generation,
vehicle.modification
].filter(Boolean).join(' / ');
trackEvent('results_shown', vehicleString, e.data.results_count);
// Update page title or breadcrumb
document.title = 'Wheels for ' + vehicleString;
// Show additional content based on results
if (e.data.results_count > 0) {
document.getElementById('related-products').style.display = 'block';
}
});
});
</script>
Error Handling and Fallbacks
document.addEventListener('DOMContentLoaded', function() {
var widgetContainer = document.getElementById('wheel-finder');
var errorContainer = document.getElementById('widget-error');
var loadingIndicator = document.getElementById('widget-loading');
try {
var widget = WheelSizeWidgets.create('#wheel-finder', {
uuid: 'your-widget-uuid',
type: 'finder-v2'
});
// Set loading timeout
var loadTimeout = setTimeout(function() {
loadingIndicator.style.display = 'none';
errorContainer.innerHTML = 'Widget is taking longer than expected to load...';
errorContainer.style.display = 'block';
}, 10000); // 10 second timeout
// Clear timeout on successful load
widget.on('ready:window', function() {
clearTimeout(loadTimeout);
loadingIndicator.style.display = 'none';
console.log('Widget loaded successfully');
});
// Handle search errors
widget.on('search:error', function(e) {
console.error('Search error:', e.data.error_message);
// Display user-friendly error message
var userMessage = 'Unable to load results. Please try again.';
if (e.data.error_message.includes('network')) {
userMessage = 'Connection error. Please check your internet connection.';
} else if (e.data.error_message.includes('timeout')) {
userMessage = 'Request timed out. Please try again.';
}
// Show error notification
showNotification(userMessage, 'error');
});
// Handle no results scenario
widget.on('results:display', function(e) {
if (e.data.results_count === 0) {
showNotification('No wheel options found for this vehicle.', 'info');
// Optionally show alternative suggestions
showAlternativeSuggestions(e.data.context.selections);
}
});
} catch (error) {
console.error('Failed to initialize widget:', error);
loadingIndicator.style.display = 'none';
errorContainer.innerHTML = 'Unable to load the wheel finder. Please refresh the page.';
errorContainer.style.display = 'block';
}
});
function showNotification(message, type) {
// Implementation of notification display
var notification = document.createElement('div');
notification.className = 'notification notification-' + type;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(function() {
notification.remove();
}, 5000);
}
function showAlternativeSuggestions(selections) {
// Implementation to show alternative vehicle suggestions
console.log('Show alternatives for:', selections);
}
Finder-v2 Widget Documentation β’ Version 2.0 β’