Skip to content

Implement Auto-Suggest

This guide explains how to implement real-time search suggestions using Gainly Auto-Suggest API.

Overview

Auto-suggest (also known as type-ahead search or autocomplete) provides real-time suggestions as users type in the search box of your site or application.

Implementation

Security Note

Never expose your Gainly API key in client-side code. Always proxy requests through your server.

The implementation involves two parts:

  1. A server endpoint that securely calls Gainly API, using your API key for authentication
  2. A client-side component that calls your server

Server Implementation

Here's an example server endpoint using Node.js/Express:

// server.js
const express = require('express');
const app = express();

app.post('/api/suggest', async (req, res) => {
    const GAINLY_API_KEY = process.env.GAINLY_API_KEY;  // Store key in environment variables
    const BASE_URL = 'https://api.gainly.ai';
    const VERSION = 'v20241104';

    try {
        const response = await fetch(`${BASE_URL}/${VERSION}/auto-suggest`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-API-Key': GAINLY_API_KEY
            },
            body: JSON.stringify({
                query: req.body.query,
                limit: req.body.limit || 5
            })
        });

        const data = await response.json();
        res.json(data);
    } catch (error) {
        console.error('Auto-suggest error:', error);
        res.status(500).json({ error: 'Failed to fetch suggestions' });
    }
});

Client Implementation

Here's the client-side JavaScript that calls your server endpoint:

class AutoSuggest {
    constructor(options = {}) {
        // Configuration with defaults
        this.minChars = options.minChars || 2;        // Min chars before triggering suggestions
        this.debounceMs = options.debounceMs || 300;  // Debounce delay in milliseconds
        this.maxResults = options.maxResults || 5;     // Max number of suggestions to show

        this.lastQuery = '';
        this.debounceTimer = null;
    }

    async getSuggestions(query) {
        try {
            const response = await fetch('/api/suggest', {  // Call your server endpoint
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    query: query,
                    limit: this.maxResults
                })
            });

            if (!response.ok) {
                throw new Error(`Server error: ${response.status}`);
            }

            return await response.json();
        } catch (error) {
            console.error('Auto-suggest error:', error);
            return null;
        }
    }

    // Example usage with an input element
    attachToInput(inputElement, callback) {
        inputElement.addEventListener('input', async (event) => {
            const query = event.target.value.trim();

            // Clear existing timer
            if (this.debounceTimer) {
                clearTimeout(this.debounceTimer);
            }

            // Don't proceed if query is too short or unchanged
            if (query.length < this.minChars || query === this.lastQuery) {
                return;
            }

            // Set new timer
            this.debounceTimer = setTimeout(async () => {
                this.lastQuery = query;
                const results = await this.getSuggestions(query);
                if (results && callback) {
                    callback(results);
                }
            }, this.debounceMs);
        });
    }
}

// Example usage
const searchInput = document.querySelector('#search-input');
const suggestionsContainer = document.querySelector('#suggestions');

const autoSuggest = new AutoSuggest({
    minChars: 2,      // Start suggesting after 2 characters
    debounceMs: 300,  // Wait 300ms after typing stops
    maxResults: 5     // Show up to 5 suggestions
});

autoSuggest.attachToInput(searchInput, (results) => {
    // Clear previous suggestions
    suggestionsContainer.innerHTML = '';

    // Display new suggestions
    results.data.forEach(item => {
        const div = document.createElement('div');
        div.textContent = item.title;
        div.classList.add('suggestion-item');
        suggestionsContainer.appendChild(div);
    });
});

Best Practices

1. Minimum Characters

Start showing suggestions after the user types at least 2-3 characters:

  • 2 characters work well for most cases
  • 3 characters might be better for large datasets
  • Consider your users' needs and your data characteristics

2. Debouncing

Implement debouncing to avoid making too many API requests:

  • Wait 300-500ms after the user stops typing
  • Clear pending requests when new characters are typed
  • This helps reduce API usage and provides a smoother experience

3. Error Handling

Always implement proper error handling:

  • Handle network errors gracefully
  • Show appropriate feedback to users
  • Log errors for debugging
  • Consider retry logic for transient failures

4. User Experience

Consider these UX improvements:

  • Show loading states while fetching suggestions
  • Handle keyboard navigation (up/down arrows)
  • Allow clicking or pressing enter to select a suggestion
  • Clear suggestions when the input loses focus

5. Mobile Considerations

For mobile implementations:

  • Consider touch interactions
  • Adjust debounce timing (might need longer delays)
  • Handle virtual keyboard events
  • Ensure suggestions are touch-friendly (larger click targets)

Additional Options

The Auto-Suggest API supports several optional parameters:

  • filter: Filter suggestions based on metadata
  • language: Specify the language of suggestions
  • tenant_id: Filter by tenant ID for multi-tenant applications

For more details about these options, see the Auto-Suggest API Reference.