Here is the pattern on almost every staffing agency site that comes to us for an SEO review. Organic traffic is up. Sessions look healthy. Then you open the landing page report: the top twenty URLs are all job adverts, the audience is overwhelmingly candidates, and search produced two employer enquiries last quarter. One was a candidate using the contact form because the apply button was broken.
The site is working. It is working for the wrong side of the market.
Recruitment SEO fails more often than other B2B SEO for one structural reason: a staffing website has two audiences with opposed intent who type nearly identical keywords. An employer searching “warehouse recruitment Leeds” wants to buy your service. A candidate searching “warehouse jobs Leeds” wants something from you for free. Build one set of pages that tries to satisfy both and you get pages that convert neither, plus relevance signals so muddled that Google cannot tell what your site is for.
Split the site down the middle, physically
The mistake looks like efficiency. You build /industries/manufacturing/ with copy saying you place manufacturing talent across the Midlands, a Get in Touch form, and halfway down a feed of live vacancies. It serves both audiences. It seems thrifty.
Three things go wrong. The copy cannot be good, because employer copy is about fill rates, vetting and replacement guarantees while candidate copy is about pay and shift patterns; write both and the page is twice as long and half as persuasive to either reader. The conversion actions collide, and “Apply now” beats “Request staff” every time, because candidates outnumber employers in raw traffic by an order of magnitude.
Worst, the internal link graph muddies. If every industry page links out to twenty vacancies and those vacancies link back, Google’s read of the page is dominated by job-listing language. You rank for “manufacturing jobs Midlands” and not for “manufacturing recruitment agency Midlands”, which is the query with money behind it.
Run two trees off the same domain with almost no crossover in body content:
- Employer tree at /hire/: service pages, sector pages written from the client’s side, engagement models, case evidence, the salary guide, the hiring-manager contact route. No job feeds inside the copy.
- Candidate tree at /jobs/: individual vacancies, browse pages, CV upload, candidate FAQs, pay and compliance explainers.
One link each way in the header or footer is fine. What you are removing is the mid-page bleed, the shared template and the double CTA. Keep the domain unified so authority pools; separate the paths so intent does not. Do this before anything else on the list.
The recruitment SEO keyword map for staffing
Build three keyword lists, and never let them share a URL.
Employer side: role plus location plus a hiring verb. The buyer verbs are recruit, recruitment, hire, hiring, staffing, staff, agency, RPO, contract, temp, headhunter. So: “engineering recruitment agency Houston”, “hire warehouse staff Manchester”, “contract staffing agency for embedded software”. Volumes are tiny; ten searches a month is normal. Value per search is enormous, because one of them is a retained assignment or a year of contract margin.
Candidate side: role plus jobs plus location. “Forklift driver jobs Leeds”, “registered nurse jobs near me”, “remote python developer jobs”. Volume is orders of magnitude higher, value per visit low but never zero, because supply is the product you sell. Candidate SEO becomes vanity traffic only when you count it as marketing performance instead of as sourcing cost avoided.
The middle: money and process questions both sides search. Salary and rate guides, cost per hire, agency fee percentages, IR35 and umbrella questions in the UK, W-2 versus C2C versus 1099 in the US, time to fill by role. A hiring manager searches “average salary for a data engineer in Chicago” while building a requisition; a candidate searches it deciding whether to move. These belong on the employer tree, because that is where the commercial follow-on lives.
One test for which side a keyword belongs to: would the searcher be annoyed if the page opened with a list of vacancies? If yes, it is an employer keyword.
JobPosting structured data, done to spec
This is the one part of recruitment SEO with an actual rulebook, and it has teeth. Google’s JobPosting structured data documentation sets out what is required and what gets you penalised.
Four properties are required: datePosted, description, hiringOrganization and title. Title means the job title only, not your advert headline with the salary and the consultant’s name in it. Description must be complete, in HTML. Recommended properties worth treating as mandatory: baseSalary, employmentType, jobLocation, validThrough, identifier and directApply. Education and experience requirements exist as beta properties.
Two technical rules break most agency implementations. Markup belongs on the most detailed leaf page possible, and Google says plainly not to add structured data to pages intended to present a list of jobs, so your /jobs/ browse page and sector filters get none at all. One posting, one page, one block of markup. Second, where the same role sits at several URLs, resolve it with canonicals rather than marking up all of them.
The content guidelines are what people skim and then regret. Google does not allow expired postings, incomplete descriptions, misrepresentation or impersonation of an organisation, keyword stuffing, or promotional content disguised as a job posting. The posting must give a way to apply, and you cannot charge applicants a fee.
Now the obligation that catches staffing sites specifically. Expired jobs have to come down promptly, and Google states that failure to take timely action on expired jobs may result in a manual action. Three acceptable ways to retire a role: set validThrough to a past date, return 404 or 410, or strip the JobPosting markup. Pick one and automate it in the ATS integration, because manually retiring roles is a job nobody in a busy agency does. Google’s guidance prefers the Indexing API over sitemaps for job posting URLs, though accurate sitemap lastmod values still help.
Two things to get right before planning around this. Google’s job search experience is not global; the documentation lists availability across 60-plus regions, so verify your market. And check what Google still supports before you build. In September 2025 Google removed the documentation for several structured data types because they are no longer shown in search results, and estimated salary was among them, alongside course info, learning video, special announcement and vehicle listing. JobPosting itself was untouched and remains supported, but if you inherited EstimatedSalary schema on a salary guide, that is dead weight. Recheck Google’s documentation updates changelog before any structured data build.
Why your 400 location pages are a doorway problem
Every staffing site eventually gets sold a programmatic build: roles multiplied by cities, 1,200 pages overnight. “Accountancy recruitment in Stockport.” “Accountancy recruitment in Stockton.” Same 400 words, one noun swapped.
Google’s spam policies name this directly. Doorway abuse is defined as sites or pages created to rank for specific, similar search queries that lead users to intermediate pages less useful than the final destination. The listed examples include pages targeted at specific regions or cities that funnel users to one page, and substantially similar pages closer to search results than a clearly defined, browseable hierarchy. That is a description of the standard recruitment location-page build.
The alternative is not “no location pages”, because local intent in staffing is real. It is fewer pages, each carrying something only writable about that place:
- Build a location page only where you have an office, a named consultant covering that patch, or a real placement history. If you cannot name a person or a client sector for the city, do not make the page.
- Put local specifics in: pay ranges from your own placement data, the employers and industrial estates you actually recruit into.
- Give it a real hierarchy. Region contains city contains sector, all linked from navigation, not only from a sitemap.
- Twelve serious city pages beat 400 spun ones. I have never seen the reverse hold.
The salary guide is the highest-value asset you can own
If you do one content project this year, make it an annual salary and rate guide for your vertical, built from your own placement data rather than aggregated from other people’s. The reason is not traffic. It is that a salary guide is one of the very few things a recruitment business can publish that other people have a reason to link to. Journalists writing about pay in your sector need a number and a source. HR teams cite it in business cases. Competitors quote it and link anyway. Your service pages never will.
- Break it by role, seniority and region rather than one national average. The regional splits get cited.
- State methodology openly: how many placements, what date range, permanent versus contract, base only or base plus bonus. Where a sample is thin, say so on that row. Credibility is the whole product.
- Publish as indexable HTML on a real URL, not a PDF behind a form. Gate a deeper cut if you must, but the numbers people link to have to be crawlable.
- Version one evergreen URL annually instead of spawning an orphan page each year, and pair it with a cost-to-hire explainer.
E-E-A-T signals when you are selling employment
Employment sits close to the money-or-life category in Google’s quality framework, and pay, immigration and licensing content gets weighed accordingly by human quality raters, even though rater judgments do not directly move rankings. These are also the signals a hiring manager uses to decide whether to reply to you.
- Named consultants with real profiles. Full name, photo, desk, years in the sector, LinkedIn, direct dial. Author the sector pages and salary commentary to those people, not to “Admin”.
- Verifiable placement evidence. Client-named case studies where you have permission, specific anonymised ones where you do not: “47 warehouse operatives across three sites in nine weeks, 91% retention at 12 weeks”. Numbers you can defend beat adjectives.
- Licensing and registration, with numbers. UK agencies work under the Conduct Regulations, and labour providers in agriculture, food processing and packaging need a Gangmasters and Labour Abuse Authority licence. US firms should show applicable state registrations, workers’ compensation cover and any employer-of-record arrangements. Plus company registration, VAT or EIN, registered address, insurance, and an address and phone number a person answers.
The technical issues specific to job boards
Recruitment sites break in ways ordinary B2B sites do not, because much of the URL inventory is created and destroyed continuously.
Expired roles. Decide the policy once. My default: keep the URL live briefly with the structured data removed and a clear “this role has closed” state plus links to similar live roles, then 410 it. If a role recurs constantly, keep one evergreen page for the role type instead of minting a URL each cycle.
Thin listing pages. A filtered page showing zero or two results is thin. Set a threshold: below it, noindex the combination or do not generate it. Empty “Jobs in Bolton” pages are how a board accumulates thousands of worthless URLs.
Faceted navigation and crawl budget. Salary sliders, shift type, radius and sort order multiply combinatorially. Index a small deliberate set that matches real demand, usually role plus location and sometimes role plus contract type. Everything else gets noindex, with sort and pagination parameters blocked from crawling. Check server logs for the share of Googlebot requests hitting facets that will never rank; on badly configured boards I have seen it pass half.
Canonicals and feeds. One vacancy posted to three sectors needs one canonical URL. Do not canonicalise job pages to the browse page, or paginated listings to page one. If you syndicate to aggregators, make your own page the canonical destination and check the apply path works without a login wall; a broken apply route is both a policy breach and a conversion leak.
Measure employer enquiries, not traffic
Report organic sessions as the headline and you guarantee bad decisions, because candidate volume swamps everything. Split every report by tree. Candidate metrics: applications started, applications completed, CVs registered, cost per applicant against what you pay job boards for the same. Employer metrics, the ones the owner cares about: enquiries from the /hire/ tree, calls attributed to employer pages, salary guide downloads with a work email, vacancies taken, assignments won, margin. Use call tracking; a serious share of employer enquiries arrive by phone and vanish from analytics otherwise.
Set the denominator honestly. Ten employer enquiries a month from a standing start is a strong outcome for a specialist agency. Ten thousand extra candidate sessions is not, on its own, an outcome at all.
A realistic 90-day order
Days 1 to 30. Set up call tracking and split reporting first, so you have a baseline. Then split the architecture: create the employer tree, rewrite service and sector pages for a client reader only, strip job feeds from employer page bodies, kill the double CTA. Audit JobPosting markup against the required properties, remove it from listing pages, automate the expired-jobs rule in the ATS integration and clear the backlog of expired roles still carrying live markup.
Days 31 to 60. Build the employer keyword map and ship the top eight to twelve pages, starting with your highest-margin role and location combinations. Fix faceted indexing and thin listing pages. Add named consultant profiles and surface licensing details. Start the salary guide: pull the data, agree the methodology, write the caveats.
Days 61 to 90. Publish the salary guide and the cost-to-hire explainer, then promote them to trade press, local business media and sector associations. Build location pages only where you can name a consultant or a placement history. Review server logs for crawl waste. Take a first read on employer enquiries, knowing that side usually takes two to three quarters to show real volume, because the queries are low-frequency and the buying cycle is slow.
What not to do: publish forty blog posts, buy a programmatic location-page package, or chase “recruitment agency” against the job board giants. The last is unwinnable and irrelevant, because nobody buys a specialist engineering search off a generic query.
Questions that come up next
Should the candidate side live on a subdomain instead? Usually no. Separate paths on one domain keep link equity pooled and are simpler to run. A subdomain makes sense only if the board is a distinct product with its own brand and commercial model.
We are an RPO, not a job board. Do we need JobPosting markup at all? Only for roles you host where candidates apply on your pages. If you never publish vacancies, skip it entirely and put everything into the employer tree, benchmark data and named-expert signals. The doorway and E-E-A-T sections still apply.
Can we mark up jobs sourced from a client’s careers site? Only if the posting is complete, accurate, hosted on your own page with a working apply route, and not a misrepresentation of the hiring organisation. Google prohibits impersonating an organisation and requires the complete description. Scraped partial listings that bounce users elsewhere are the intermediate-page pattern the doorway policy targets.
If you would rather have this done than described, AB7 Solutions works on both halves of it. We run recruitment, RPO, C2C and contract staffing delivery, so we know why the employer page and the candidate page have to say different things, and we run SEO, AEO and GEO programmes plus the web and API builds behind them, including ATS integrations that retire expired roles on schedule. Send us the domain and we will tell you whether you have a doorway-page problem or just bad architecture. Call +1 321 341 7733, or email ab@ab7solutions.com or director@ab7solutions.com. More at www.ab7solutions.com.
Sources: Google Search Central, Job posting (JobPosting) structured data (properties, content and technical guidelines, expired-posting removal and manual action warning, Indexing API guidance, regional availability); Google Search Central, Spam policies for Google web search (doorway abuse); Google Search Central, Latest Google Search documentation updates (9 September 2025 entry removing documentation for course info, estimated salary, learning video, special announcement and vehicle listing).