Skip to main content

GL Search & Search Results Integration Guide

Quick guide for integrating gl-search and gl-search-results components together

For 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:

  1. gl-search - Search input component with location autocomplete
  2. gl-search-results - Display search results with filtering and pagination

Key Integration Points:

  • Search component dispatches gl-search event 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โ€‹


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