Restaurant & Store Finder
This example demonstrates how to create a specialised location finder that searches for
specific business types. By using the includedPrimaryTypes parameter, you can build targeted search experiences for restaurants, cafés, shops, and other
establishments.
Live Demo
Select a business type below, then search for locations near you. The autocomplete will only show results matching your selected category.
powered by
How It Works
This example demonstrates how to build a specialised location finder by filtering results to specific business types.
- Place Type Filtering: Use the
includedPrimaryTypesparameter inrequestParamsto limit results to specific business categories like restaurants, cafés, or pharmacies. - Dynamic Type Switching: Update the search filter on-the-fly using
setRequestParams()when users select different business types, providing a seamless filtering experience. - Rich Place Information: The response includes valuable business data such as ratings, review counts, contact information, price levels, and business status that you can display to users.
- Enhanced User Experience: By focusing searches on specific business types, you eliminate irrelevant results and help users find exactly what they're looking for more quickly.
- Practical Applications: This pattern is perfect for restaurant finders, store locators, service directories, and any application where users need to find specific types of businesses or locations.
<script> import { PlacesAutocomplete } from 'places-autocomplete-js'; document.addEventListener('DOMContentLoaded', () => { let selectedType = 'restaurant'; let autocomplete; // Place type buttons const placeTypes = [ { value: 'restaurant', label: 'Restaurants' }, { value: 'cafe', label: 'Cafés' }, { value: 'bar', label: 'Bars' }, { value: 'bakery', label: 'Bakeries' }, { value: 'supermarket', label: 'Supermarkets' }, { value: 'pharmacy', label: 'Pharmacies' }, { value: 'gas_station', label: 'Petrol Stations' }, { value: 'bank', label: 'Banks' } ]; // Initialise Places Autocomplete autocomplete = new PlacesAutocomplete({ containerId: 'restaurant-autocomplete-container', googleMapsApiKey: 'YOUR_GOOGLE_MAPS_API_KEY', onResponse: (placeDetails) => { console.log('Place Selected:', placeDetails); displayPlaceInfo(placeDetails); }, onError: (error) => { console.error('Autocomplete Error:', error.message || error); }, requestParams: { includedPrimaryTypes: [selectedType] // Filter by specific business type }, fetchFields: [ 'displayName', 'formattedAddress', 'rating', 'userRatingCount', 'internationalPhoneNumber', 'types', 'priceLevel', 'businessStatus', 'websiteURI', 'regularOpeningHours', 'editorialSummary' ], options: { placeholder: 'Search for restaurants, cafés, stores...', clear_input: false } }); // Create place type filter buttons const typeContainer = document.getElementById('type-filter-container'); placeTypes.forEach(type => { const button = document.createElement('button'); button.textContent = type.label; button.classList.add('type-button'); if (type.value === selectedType) { button.classList.add('active'); } button.addEventListener('click', () => { selectedType = type.value; // Update active button styling document.querySelectorAll('.type-button').forEach(btn => { btn.classList.remove('active'); }); button.classList.add('active'); // Update autocomplete to search for new type autocomplete.setRequestParams({ includedPrimaryTypes: [selectedType] }); // Clear the input and results autocomplete.clear(); document.getElementById('place-info').innerHTML = ''; }); typeContainer.appendChild(button); }); function displayPlaceInfo(placeDetails) { const infoContainer = document.getElementById('place-info'); // Format price level const formatPriceLevel = (level) => { const priceLevels = { 'INEXPENSIVE': { text: 'Budget-friendly', symbol: '£' }, 'MODERATE': { text: 'Moderate pricing', symbol: '££' }, 'EXPENSIVE': { text: 'Upmarket', symbol: '£££' }, 'VERY_EXPENSIVE': { text: 'Fine dining', symbol: '££££' } }; return priceLevels[level] || { text: level, symbol: '' }; }; // Build HTML for place information let html = ` <div class="place-card"> <div class="place-header"> <h3>${placeDetails.displayName}</h3> ${placeDetails.businessStatus ? `<span class="status ${placeDetails.businessStatus === 'OPERATIONAL' ? 'open' : 'closed'}"> ${placeDetails.businessStatus === 'OPERATIONAL' ? 'Open' : 'Closed'} </span>` : ''} </div> ${placeDetails.editorialSummary ? `<p class="editorial-summary">${placeDetails.editorialSummary}</p>` : ''} ${placeDetails.types ? `<div class="types"> ${placeDetails.types .filter(t => !['point_of_interest', 'establishment', 'food'].includes(t)) .slice(0, 5) .map(type => `<span class="type-badge">${type.replace(/_/g, ' ')}</span>`) .join('')} </div>` : ''} <div class="rating-price"> ${placeDetails.rating ? `<div class="rating"> ★ ${placeDetails.rating.toFixed(1)} ${placeDetails.userRatingCount ? `<span>(${placeDetails.userRatingCount.toLocaleString()} reviews)</span>` : ''} </div>` : ''} ${placeDetails.priceLevel ? `<div class="price"> ${formatPriceLevel(placeDetails.priceLevel).text} <span>(${formatPriceLevel(placeDetails.priceLevel).symbol})</span> </div>` : ''} </div> <div class="contact-details"> <h4>Contact Details</h4> ${placeDetails.formattedAddress ? `<div class="detail"> <span class="icon">📍</span> <span>${placeDetails.formattedAddress}</span> </div>` : ''} ${placeDetails.internationalPhoneNumber ? `<div class="detail"> <span class="icon">📞</span> <a href="tel:${placeDetails.internationalPhoneNumber}"> ${placeDetails.internationalPhoneNumber} </a> </div>` : ''} ${placeDetails.websiteURI ? `<div class="detail"> <span class="icon">🌐</span> <a href="${placeDetails.websiteURI}" target="_blank" rel="noopener noreferrer"> Visit website </a> </div>` : ''} ${placeDetails.id ? `<div class="detail"> <span class="icon">🧭</span> <a href="https://www.google.com/maps/search/?api=1&query=Google&query_place_id=${placeDetails.id}" target="_blank" rel="noopener noreferrer"> Get directions </a> </div>` : ''} </div> ${placeDetails.regularOpeningHours?.weekdayDescriptions ? `<div class="opening-hours"> <h4>Opening Hours</h4> ${placeDetails.regularOpeningHours.weekdayDescriptions .map(hours => `<div class="hours">🕐 ${hours}</div>`) .join('')} </div>` : ''} </div> `; infoContainer.innerHTML = html; } }); </script> <!-- Place Type Filter Buttons --> <div id="type-filter-container" class="type-filters"> <!-- Buttons will be dynamically created here --> </div> <!-- Autocomplete Search Input --> <div id="restaurant-autocomplete-container"></div> <!-- Place Information Display --> <div id="place-info"></div> <style> .type-filters { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem; } .type-button { padding: 0.5rem 1rem; border: 1px solid #ccc; border-radius: 0.5rem; background: #f9fafb; cursor: pointer; transition: all 0.2s; } .type-button.active { background: #4f46e5; color: white; border-color: #4f46e5; } .place-card { margin-top: 1.5rem; padding: 1.5rem; border: 1px solid #e5e7eb; border-radius: 0.5rem; background: white; } .place-header { display: flex; justify-content: space-between; align-items: start; margin-bottom: 1rem; } .status { padding: 0.25rem 0.75rem; border-radius: 0.25rem; font-size: 0.875rem; } .status.open { background: #dcfce7; color: #166534; } .status.closed { background: #fee2e2; color: #991b1b; } .editorial-summary { font-style: italic; color: #6b7280; margin-bottom: 1rem; } .types { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem; } .type-badge { padding: 0.25rem 0.75rem; background: #eef2ff; color: #4f46e5; border-radius: 0.25rem; font-size: 0.875rem; } .rating-price { display: flex; gap: 2rem; padding: 1rem 0; border-top: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; margin-bottom: 1rem; } .contact-details h4, .opening-hours h4 { font-size: 0.875rem; font-weight: 600; text-transform: uppercase; color: #6b7280; margin-bottom: 0.75rem; } .detail { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem; } .detail a { color: #4f46e5; text-decoration: none; } .opening-hours { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid #e5e7eb; } .hours { margin-bottom: 0.5rem; font-size: 0.875rem; } </style>