Search Bar Example
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:
- The token endpoint used to authenticate
/suggestions
/categories
(optional)
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
.
Below is an example of how to start. It is 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.
function SearchBar () {
const [searchText, setSearchText] = useState('');
const [results, setResults] = useState([]);
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(`${API_URL}/token`, {
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}`,
'client-id': CLIENT_ID,
},
});
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>
);
}