Build a search bar
This guide will walk you through the steps to build a search bar. You will learn how to authenticate your app, how to search for products and how to limit the search to a specific category. To do this you will need to interact with the following endpoints:
/token
from the identity provider/suggestions
/categories
(optional)
The first step is to authenticate your app with your client-id
and client-secret
in the identity provider served at https://auth.pj.nu. This will give you an access token to use in the following requests. The access token is valid for specific amount of time (expires_in
field in the response).
Remember to store your credentials and access token in a safe location in a backend service.
You can use the suggestions endpoint to find products with a text query. Simply set the product query parameter to the product the user is searching for e.g product=batman
.
It's also possible to limit the search within a category e.g product=batman&category=board-games
, to find which categories you can use make a request to the /categories
endpoint. To see the full documentation go to the API Reference.
To recieve attribution for clicks you have to append your ref to the request e.g product=batman&ref=your-ref
.
Example
Below is an example to get you started. It's a React component that uses the useEffect hook to fetch the access token and perform the search. It also uses the useState hook to store the search text and the results. The search is debounced with 250ms to avoid making too many requests as the user is typing.
Requirements
- Valid client ID and client secret, contact Prisjakt to gain access to the API.
function SearchBar () { const [searchText, setSearchText] = useState(''); const [results, setResults] = useState([]); const AUTH_URL = 'https://auth.pj.nu/oauth2/token'; const API_URL = 'https://api.pj.nu/partner-search'; const CLIENT_ID = ''; const CLIENT_SECRET = ''; useEffect(() => { const fetchAccessToken = async () => { const urlencoded = new URLSearchParams(); urlencoded.append("grant_type", "client_credentials"); urlencoded.append("client_id", CLIENT_ID); urlencoded.append("client_secret", CLIENT_SECRET); const response = await fetch(AUTH_URL, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: urlencoded, }); const data = await response.json(); return data.access_token; }; const performSearch = async (accessToken) => { const response = await fetch(`${API_URL}/suggestions?market=gb&product=${searchText}`, { headers: { Authorization: `Bearer ${accessToken}`, }, }); const results = await response.json(); if (!results.data) { setResults([]); return; } setResults(results.data); }; // Debounce the performSearch function with 250ms const timerId = setTimeout(async () => { if (searchText) { try { const token = await fetchAccessToken(); performSearch(token); } catch (error) { console.error('Error:', error); } } else { setResults([]); } }, 250); return () => { clearTimeout(timerId); }; }, [searchText]); const handleSearch = (e) => { const searchValue = e.target.value; setSearchText(searchValue); }; return ( <div> <input type="text" value={searchText} onChange={handleSearch} placeholder="Search..." /> <div> {results.map(({productName, images }, index) => ( <div key={index} style={ {display: 'flex', 'align-items': 'center', gap: '8px'}}> <img src={images.small} alt={productName} style={{height: '48px', width: 'auto'}} /> <p style={{'font-size': '16px'}}>{productName}</p> </div> ))} </div> </div> ); }