Use case
Employer at sign-up
Instead of a text field where each user writes their organisation as they like, a picker suggests from the archive as they type and stores the brand’s slug. Each organisation gets one identity in your database, with its logo ready for the team page.
Endpoints
- GET /api/v1/search/suggest
- GET /api/v1/brands/{slug}counts as a pull
- Products
- Search, identity data
- Pulls
- One per brand picked the first time
- Search
- Not counted
The problem, and the fix
When each user types their organisation themselves, one organisation gets many spellings: «stc», «Saudi Telecom», «STC Group». You can’t tell how many people share an employer, and you can’t show its logo.
A picker that suggests from the archive and stores slug gives each organisation one id. You know who works where, can show the logo on team pages, invoices and reports, and the logo updates when the organisation changes its identity.
Who it’s for
Hiring and team platforms
The employer on profiles and team pages.
Government and education platforms
The organisation a user belongs to, by id not free text.
Events and conferences
Each attendee’s organisation on their badge and in the attendee list.
Try it
Type an organisation in the sign-up form and pick a suggestion, then see its card as it will appear on the team page.
Where do you work?
Search for it by the name people know.
Build it
- 01
Get a key
Open a developer account in the console and make a key. The free plan is enough to start, and the key stays on your server in an environment variable.
- 02
A suggestions route of yours
A route on your server takes what the user typed, calls search with your key, and returns slug, names and image.
- 03
The field in the form
Wait 250 ms after the last letter, cancel the previous request, and make the list work by keyboard.
- 04
Store the slug
slugon the user’s record, not the name or the logo link. - 05
Show the logo
Read the brand’s record once and keep it; read it again when
updatedAtchanges. - 06
When it isn’t there
Let the name be entered as it is, and point the user to «Request a logo» if you like.
The suggestions route
brand-picker.js
// On your server, behind your own route (say /brand-suggest): it holds the key.const base = 'https://new.wasmenia.com';/** Suggestions for what the user has typed so far. */export async function suggest(text, signal) { const q = text.trim(); if (q.length < 2) return []; // shorter is answered empty and not counted const url = new URL('/api/v1/search/suggest', base); url.searchParams.set('q', q); const res = await fetch(url, { signal, headers: { Authorization: `Bearer ${process.env.WASMENIA_API_KEY}` }, }); if (res.status === 429) { // Over your plan's requests a minute: wait, then try again. const wait = Number(res.headers.get('Retry-After') ?? 60); throw Object.assign(new Error('rate_limited'), { wait }); } if (!res.ok) throw new Error(`HTTP ${res.status}`); const { items } = await res.json(); return items.map((b) => ({ slug: b.slug, // what you store label: b.nameAr, secondary: b.nameEn, // may be null image: b.thumbUrl, // may be null: show the name alone verified: b.isVerified, }));}With the input field
// In the page: it asks your route, never Wasmenia with your key.let timer;let pending; // the request still in flight, if anyinput.addEventListener('input', () => { clearTimeout(timer); timer = setTimeout(async () => { pending?.abort(); // a newer keystroke makes the older answer useless pending = new AbortController(); try { const url = '/brand-suggest?q=' + encodeURIComponent(input.value); const res = await fetch(url, { signal: pending.signal }); if (res.status === 429) return pauseFor(Number(res.headers.get('Retry-After') ?? 60)); render(await res.json()); } catch (e) { if (e.name === 'AbortError') return; // replaced by a newer request showError(); } }, 250);});How many pulls it costs
Search isn’t counted. A pull is when you read the brand’s record after a pick: if you keep the record, a thousand users from 40 different organisations are 40 pulls, then one per organisation that changes.
Questions
Should I forbid free text?
No. Not every organisation is in the archive. Suggest first, and accept the name as typed when the user doesn’t find theirs.
Why not call from the browser?
The key is a secret, and browsers on other sites can’t send it. A small route on your server holds it.
Products it uses
Identity data
The name in both languages, other names, colours and their source, fonts and guidelines.
Search
Up to 8 suggestions by name as people type, in Arabic or English.
Build it step by step
The request, the wait between letters, cancelling the previous request, and 429.