GL Search & Search Results Integration Guide
Quick guide for integrating
gl-searchandgl-search-resultscomponents togetherFor detailed documentation of individual components, see:
๐ Table of Contentsโ
Overviewโ
This guide shows how to integrate gl-search and gl-search-results components to create a complete search experience:
- gl-search - Search input component with location autocomplete
- gl-search-results - Display search results with filtering and pagination
Key Integration Points:
- Search component dispatches
gl-searchevent with search parameters - Results component listens for search events and fetches data
- Both components share the same JWT token and environment
Installationโ
npm install @gift-card-market/gl-search @gift-card-market/gl-search-results
or
yarn add @gift-card-market/gl-search @gift-card-market/gl-search-results
React Integrationโ
Basic Setup (React)โ
import { GlSearch } from '@gift-card-market/gl-search';
import { GlSearchResults } from '@gift-card-market/gl-search-results';
import '@gift-card-market/gl-search/dist/style.css';
import '@gift-card-market/gl-search-results/dist/style.css';
function SearchPage() {
const jwt = 'your-jwt-token';
const environment = 'development'; // or 'production'
return (
<div>
{/* Search Bar */}
<GlSearch
environment={environment}
jwt={jwt}
google_api_key="your-google-api-key"
/>
{/* Search Results */}
<GlSearchResults
environment={environment}
jwt={jwt}
/>
</div>
);
}
Complete Example (React)โ
import {GlSearchResults, type GlSearchResultsHandle, SearchResultsEvents} from '@gift-card-market/gl-search-results';
import {GlSearch, type GlSearchBarHandle} from '@gift-card-market/gl-search';
import './index.css';
import '@gift-card-market/gl-search-results/dist/style.css';
import '@gift-card-market/gl-search/dist/style.css';
import {useEffect, useRef} from 'react';
export default function SearchPage() {
const data = {
banner_color: 'darkblue',
banner_text: [
`Do they love burgers? ๐ Search for their <strong style="color: #ffe606"><em>favorite</em></strong> below. <em>Bet we have it!</em>`,
`Youโve got <strong style="color: #ffe606"><em>great taste</em></strong>. Weโve got gift cards to match.`,
`Foodie-level gifts? ๐ฝ๏ธ Yeah, <strong style="color: #ffe606"><em>weโre ready</em></strong> for that challenge.`,
`Youโd gift a taco truck? <strong style="color: #ffe606"><em>Respect.</em></strong> ๐ฎ We got โem.`,
],
search_text: [
{
content: `(thinking <u>top smash burger joints</u>?)`,
key: 'smash burgers',
},
{
content: `(thinking <u>best lunch spots near me</u>?)`,
key: 'best lunch spots',
},
{
content: `(thinking <u>top chef-owned restaurants</u>?)`,
key: 'chef-owned restaurants',
},
{
content: `(thinking <u>local taquerias</u>?)`,
key: 'local taquerias',
},
],
search_term: '',
search_button_color: {
text: 'yellow',
background: 'green',
},
};
// Ref to access component methods
const searchRef = useRef<GlSearchBarHandle>(null);
const searchResultsRef = useRef<GlSearchResultsHandle>(null);
// Handler to focus on input
const handleFocusClick = () => {
console.log('๐ฏ Calling focus() method');
searchRef.current?.focus();
};
// Handler to set query with example data
const handleSetQueryClick = () => {
const exampleQuery = 'Location=New York&SearchTerm=pizza';
console.log('๐ฏ Calling setQuery() method with:', exampleQuery);
searchRef.current?.setQuery(exampleQuery);
};
// Handler to refresh results
const handleRefreshResults = () => {
console.log('๐ Calling refreshResults() method');
searchResultsRef?.current?.refreshResults && searchResultsRef.current.refreshResults();
};
useEffect(() => {
const handleGlSearch = (e: CustomEvent) => {
console.log('๐ gl:search event:', e.detail);
};
const handleGlClear = (e: CustomEvent) => {
console.log('๐งน gl:clear event:', e.detail);
};
const handleResultClick = (e: CustomEvent) => {
console.log(`๐ฑ๏ธ ${SearchResultsEvents.RESULT_CLICK} event:`, e.detail);
};
const handlePageChange = (e: CustomEvent) => {
console.log(`๐ ${SearchResultsEvents.PAGE_CHANGE} event:`, e.detail);
};
document.addEventListener('gl:search', handleGlSearch as EventListener);
document.addEventListener('gl:clear', handleGlClear as EventListener);
document.addEventListener(SearchResultsEvents.RESULT_CLICK, handleResultClick as EventListener);
document.addEventListener(SearchResultsEvents.PAGE_CHANGE, handlePageChange as EventListener);
// Demo using ref methods
console.log('๐ Search Component Ref Methods:', searchRef.current);
// Cleanup
return () => {
document.removeEventListener('gl:search', handleGlSearch as EventListener);
document.removeEventListener('gl:clear', handleGlClear as EventListener);
document.removeEventListener(SearchResultsEvents.RESULT_CLICK, handleResultClick as EventListener);
document.removeEventListener(SearchResultsEvents.PAGE_CHANGE, handlePageChange as EventListener);
};
}, []);
return (
<>
<div
style={{
padding: '20px',
background: '#f5f5f5',
borderBottom: '2px solid #ddd',
marginBottom: '20px',
}}
>
<h3 style={{margin: '0 0 15px 0', fontSize: '18px', fontWeight: 'bold'}}>
๐ฎ Demo Control Panel - Test Ref Methods
</h3>
<div style={{display: 'flex', gap: '10px', flexWrap: 'wrap'}}>
<button
onClick={handleFocusClick}
style={{
padding: '10px 20px',
backgroundColor: '#4CAF50',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '600',
}}
>
๐ฏ Focus Input
</button>
<button
onClick={handleSetQueryClick}
style={{
padding: '10px 20px',
backgroundColor: '#2196F3',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '600',
}}
>
๐ Set Query (New York / pizza)
</button>
<button
onClick={handleRefreshResults}
style={{
padding: '10px 20px',
backgroundColor: '#FF9800',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: '600',
}}
>
๐ Refresh Results
</button>
</div>
<p style={{margin: '10px 0 0 0', fontSize: '12px', color: '#666'}}>
๐ก Tip: Open Console (F12) to see dispatched events
</p>
</div>
<GlSearch
ref={searchRef}
environment={'development'}
jwt={process.env.JWT_TOKEN ?? ''}
data={data}
google_api_key={process.env.GOOGLE_API_KEY}
debounce_ms={250}
/>
<GlSearchResults
ref={searchResultsRef}
configuration={{
layout: 'list',
showCYOBanner: true,
showPurchaseButton: true,
purchaseButtonEnabled: true,
purchaseButtonText: 'Purchase',
purchaseButtonColor: '#ED1164',
numberOfResults: 10,
}}
environment={'development'}
jwt={process.env.JWT_TOKEN ?? ''}
/>
</>
);
}
Vanilla JS Integrationโ
Basic Setup (Vanilla JS)โ
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Search Integration</title>
<!-- Include both component bundles -->
<script src="./node_modules/@gift-card-market/gl-search/dist/browser/gl-search.global.js"></script>
<script src="./node_modules/@gift-card-market/gl-search-results/dist/browser/gl-search-results.global.js"></script>
<!-- Include both stylesheets -->
<link rel="stylesheet" href="./node_modules/@gift-card-market/gl-search/dist/browser/gl-search.css">
<link rel="stylesheet" href="./node_modules/@gift-card-market/gl-search-results/dist/browser/gl-search-results.css">
</head>
<body>
<!-- Search Container -->
<div id="search-container"></div>
<!-- Results Container -->
<div id="results-container"></div>
<script>
const jwt = 'your-jwt-token';
const environment = 'development';
// Initialize Search Component
function initializeSearch() {
const searchContainer = document.getElementById('search-container');
const searchEl = GlSearchLib.createSearchElement({
environment: environment,
jwt: jwt,
google_api_key: 'your-google-api-key',
});
searchContainer.appendChild(searchEl);
}
// Initialize Results Component
function initializeResults() {
const resultsContainer = document.getElementById('results-container');
const resultsEl = GlSearchResultsLib.createSearchResultsElement({
environment: environment,
jwt: jwt,
});
resultsContainer.appendChild(resultsEl);
}
// Initialize both components
window.addEventListener('DOMContentLoaded', () => {
initializeSearch();
initializeResults();
});
</script>
</body>
</html>
Complete Working Example (Vanilla JS)โ
See the complete working implementation in public/search/vanilla-js.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GlSearch & GlSearchResult - Vanilla JS Demo (Pure JavaScript)</title>
<script src="../../node_modules/@gift-card-market/gl-search/dist/browser/gl-search.global.js"></script>
<link rel="stylesheet" href="../../node_modules/@gift-card-market/gl-search/dist/browser/gl-search.css">
<script
src="../../node_modules/@gift-card-market/gl-search-results/dist/browser/gl-search-results.global.js"></script>
<link rel="stylesheet"
href="../../node_modules/@gift-card-market/gl-search-results/dist/browser/gl-search-results.css">
<link rel="stylesheet" href="./vanilla-js.css">
</head>
<body>
<div class="demo-container">
<!-- Control Panel -->
<div class="control-panel">
<h3>๐ฎ Demo Control Panel - Test Component Methods</h3>
<div class="button-group">
<button class="demo-button btn-focus" onclick="handleFocus()">
๐ฏ Focus Input
</button>
<button class="demo-button btn-set-query" onclick="handleSetQuery()">
๐ Set Query (New York / pizza)
</button>
</div>
<p class="tip">๐ก Tip: Watch the Event Log below to see dispatched events</p>
</div>
<!-- GlSearch Web Component Container -->
<div id="search-container"></div>
</div>
<script>
// Data configuration with all available properties
const searchData = {
// Banner background color
banner_color: 'darkblue',
// Array of rotating banner texts (supports HTML: strong, em, u, etc.)
banner_text: [
`Do they love burgers? ๐ Search for their <strong style="color: #ffe606"><em>favorite</em></strong> below. <em>Bet we have it!</em>`,
`You've got <strong style="color: #ffe606"><em>great taste</em></strong>. We've got gift cards to match.`,
`Foodie-level gifts? ๐ฝ๏ธ Yeah, <strong style="color: #ffe606"><em>we're ready</em></strong> for that challenge.`,
`You'd gift a taco truck? <strong style="color: #ffe606"><em>Respect.</em></strong> ๐ฎ We got 'em.`,
],
// Array of search placeholder suggestions (supports HTML: u, strong, em, etc.)
search_text: [
{
content: `(thinking <u>top smash burger joints</u>?)`,
key: 'smash burgers',
},
{
content: `(thinking <u>best lunch spots near me</u>?)`,
key: 'best lunch spots',
},
{
content: `(thinking <u>top chef-owned restaurants</u>?)`,
key: 'chef-owned restaurants',
},
{
content: `(thinking <u>local taquerias</u>?)`,
key: 'local taquerias',
},
],
// Initial search term
search_term: '',
// Search button colors
search_button_color: {
text: 'yellow',
background: 'green',
},
};
// Store reference to the web component element
let searchElement = null;
let searchResultElement = null;
const searchParams = new URLSearchParams(window.location.search);
const jwtToken = searchParams.get('jwt');
// Initialize the web component (Pure Vanilla JS!)
function initializeComponent() {
initSearchBar();
initSearchResult();
logToConsole('Web Component initialized successfully');
}
function initSearchBar() {
const container = document.getElementById('search-container');
// Create the custom element <gl-search>
searchElement = document.createElement('gl-search');
// Set required attributes
searchElement.setAttribute('environment', 'development');
searchElement.setAttribute('jwt', jwtToken);
// Set optional attributes
searchElement.setAttribute('google_api_key', '');
searchElement.setAttribute('debounce_ms', '250');
// Set data as JSON string
searchElement.setAttribute('data', JSON.stringify(searchData));
// Append to container
container.appendChild(searchElement);
}
function initSearchResult() {
const container = document.getElementById('search-container');
// Create the custom element <gl-search>
searchResultElement = document.createElement('gl-search-results');
// Set required attributes
searchResultElement.setAttribute('environment', 'development');
searchResultElement.setAttribute('jwt', jwtToken);
// Append to container
container.appendChild(searchResultElement);
}
function logToConsole(message, data) {
if (data) {
console.log('[GlSearch Demo] ' + message, data);
} else {
console.log('[GlSearch Demo] ' + message);
}
}
// Listen to 'gl:search' event - main search event
document.addEventListener('gl:search', function (e) {
logToConsole('๐ gl:search event', e.detail);
});
// Listen to 'gl:clear' event - event when search is cleared
document.addEventListener('gl:clear', function (e) {
logToConsole('๐งน gl:clear event', e.detail);
});
// Handler to focus on input
function handleFocus() {
logToConsole('๐ฏ Attempting to focus on location input');
if (searchElement) {
searchElement.focus();
logToConsole('โ
Input focused successfully');
} else {
console.warn('Location input not found yet. Component may still be initializing.');
}
}
// Handler to set query with example data
function handleSetQuery() {
const exampleQuery = 'Location=New York&SearchTerm=pizza';
if (searchElement) {
logToConsole('๐ฏ Setting query attribute', exampleQuery);
// Set attribute on web component - Pure Vanilla JS!
searchElement.setQuery(exampleQuery);
logToConsole('โ
Query set successfully');
} else {
console.warn('Search element not initialized yet');
}
}
// Initialize component when DOM is ready (Pure Vanilla JS!)
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeComponent);
} else {
initializeComponent();
}
</script>
</body>
</html>
Event Flowโ
The integration works through custom events:
sequenceDiagram
User->>gl-search: Enter search term & location
gl-search->>Window: Dispatch 'gl-search' event
Window->>gl-search-results: Event received
gl-search-results->>API: Fetch search results
API->>gl-search-results: Return results
gl-search-results->>Window: Dispatch 'gl-search-results-loaded'
gl-search-results->>User: Display results
Additional Resourcesโ
- GL Search Bar: See GL-SEARCH-BAR-GUIDE.md for complete search component documentation
- GL Search Results: See GL-SEARCH-RESULTS-GUIDE.md for complete results component documentation
Supportโ
For issues or questions:
- Check individual component guides linked above
- Review the example files in
/public/search/and/src/pages/search/ - Contact the development team
Last Updated: January 16, 2026