LinkedIn

geo-typeahead

linkedin.com
InstallationInstalls just this skill for your agent
Side effectread
Authsession
Needsnavigate · evaluate
Summary

Resolve a location name to its LinkedIn geoUrn (e.g.

Params
{"q":"string"}
Returns
{"count":"int","results":"array of { name, geoUrn, geoUrnParam }","bestName":"string|null","bestGeoUrn":"string|null","bestGeoUrnParam":"string ('[\"ID\"]' or '' if there is no match)"}
SKILL.md31 lines

Intent

Resolve a location name to its LinkedIn geoUrn (e.g. 'Argentina' -> 100446943), to feed the geoUrn param of linkedin-search-people. Uses the classic Voyager GraphQL typeahead (queryId voyagerSearchDashReusableTypeahead, typeaheadUseCase:JOBS) which returns the SAME IDs the people-search filter uses (verified: Argentina=100446943). In-page fetch with session cookies. PARAM: q = the location text; TIP: passing 'city country' (e.g. 'Cordoba Argentina', 'Madrid Spain') disambiguates and improves the first match. Returns up to ~20 candidates ordered by relevance in results[], PLUS best* fields of the top match for easy chaining. bestGeoUrnParam already comes in '["ID"]' format ready for search-people; if there is NO match (e.g. typo 'Argntina') bestGeoUrnParam is '' (empty string) on purpose, so downstream searches run WITHOUT a location filter instead of breaking. NOTE: depends on the queryId hash that ROTATES on every LinkedIn deploy; if it returns empty for a clearly valid query (Argentina, Madrid), recapture the hash from the location typeahead at /jobs/search/. Requires an active session.

Preconditions

Execute

  1. navigate → https://www.linkedin.com/jobs/
  2. evaluate the Extractor below with params. It does the in-page work and returns the JSON in returns.

Extractor

( async (root, params) => { const q = (params && (params.q || params.query)) || ''; const csrf = (document.cookie.match(/JSESSIONID="?([^";]+)"?/)||[])[1] || ''; const hash = 'voyagerSearchDashReusableTypeahead.4c7caa85341b17b470153ad3d1a29caf'; const geoTypes = 'POSTCODE_1,POSTCODE_2,POPULATED_PLACE,ADMIN_DIVISION_1,ADMIN_DIVISION_2,COUNTRY_REGION,MARKET_AREA,COUNTRY_CLUSTER'; const url = '/voyager/api/graphql?variables=(keywords:'+encodeURIComponent(q)+',query:(typeaheadFilterQuery:(geoSearchTypes:List('+geoTypes+')),typeaheadUseCase:JOBS),type:GEO)&queryId='+hash; const r = await fetch(url, { headers:{'csrf-token':csrf,'accept':'application/json','x-restli-protocol-version':'2.0.0'}, credentials:'include' }); if(!r.ok) return { error:'http '+r.status, count:0, bestGeoUrnParam:'', results:[] }; const d = await r.json(); const dd = d.data || {}; const node = dd.searchDashReusableTypeaheadByType || (dd.data && dd.data.searchDashReusableTypeaheadByType) || {}; const els = node.elements || []; const results = els.map(e => { const id = e.trackingUrn ? String(e.trackingUrn).split(':').pop() : null; return { name: e.title && e.title.text, geoUrn: id, geoUrnParam: id ? ('["'+id+'"]') : null }; }).filter(x => x.geoUrn); const best = results[0] || {}; return { count: results.length, bestName: best.name || null, bestGeoUrn: best.geoUrn || null, bestGeoUrnParam: best.geoUrnParam || '', results }; } )

Success assertion

Response text contains "LinkedIn".