
JobPosting 構造化データ 徹底解説 - Google 求人検索に載せるための JSON-LD 実装とコンテンツ運用
求人サイトや採用ページを Google 検索の 求人検索エクスペリエンス(Google for Jobs) に載せるためには、JobPosting の構造化データ(JSON-LD)を正しく埋め込む必要があります。本記事では公式ドキュメントをもとに、必須/推奨プロパティ、リモートワーク対応、学歴・経験のベータプロパティ、コンテンツポリシーや審査エラーの直し方まで、実装担当者目線で整理します。
本記事は 2026年5月14日時点 の公式ドキュメント(最終更新 2026-02-20 UTC)をもとに整理しています。仕様変更が頻繁な領域なので、本番投入前には必ず公式の求人情報(JobPosting)の構造化データを併せて確認してください。
JobPosting 構造化データとは
JobPosting は schema.org が定義する「求人1件」を表す構造化データのタイプです。求人情報ページに JSON-LD で JobPosting を埋め込むと、Google 検索で次のような特別な見え方を獲得できます。
- 求人検索カルーセル / 求人カードへの掲載
- 勤務地・職種・在宅勤務などのフィルタ対応
- ロゴ、評価、給与レンジなどのリッチな表示
- 求人詳細から自社サイトへの動線(直接応募)
雇用主/求人サイトにとってのメリットは公式ドキュメントが3点に整理しています。
| メリット | 内容 |
|---|---|
| よりインタラクティブな結果 | ロゴ・レビュー・評価・求人詳細を目立たせて表示 |
| 意欲的な応募者の流入 | 場所・役職などで絞り込まれた応募者にリーチ |
| 検出とコンバージョン機会の増加 | 求職者が新たな経路で求人にアクセス |
なお、求人サイト側で 他の雇用主のレビューを出している場合は別途 EmployerAggregateRating 構造化データの追加も検討するよう案内されています。
構造化データを追加するまでの全体フロー
公式ドキュメントが提示する手順をひととおり並べると、こうなります。
- Googlebot がサイトを効率的にクロールできることを確認する(
robots.txt/ 認証 /noindexチェック) - 同一求人を複数 URL でホストする場合は 正規 URL を
rel="canonical"で示す - 必須+推奨プロパティを JSON-LD で記述する
- 技術ガイドラインと コンテンツポリシーに従う
- リッチリザルト テストで検証 + プレビュー
- 数ページ本番に出して、Search Console の URL 検査ツールで Google 視点を確認
- Indexing API とサイトマップで Google に最新情報を継続して通知する
求人情報の URL に対しては サイトマップより Indexing API の方が公式に推奨されている、という点が他の構造化データと違うポイントです。新規求人・更新・削除はすべて Indexing API で通知し、サイト全体の整合性確認用にサイトマップも送る、というのが現状のベストプラクティスです。
標準的な求人情報の JSON-LD(最小例)
公式の標準例をそのまま貼ると次のとおり。<head> 内に <script type="application/ld+json"> で埋め込みます。
<html>
<head>
<title>Software Engineer</title>
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "JobPosting",
"title": "Software Engineer",
"description": "<p>Google aspires to be an organization that reflects the globally diverse audience that our products and technology serve.</p>",
"identifier": {
"@type": "PropertyValue",
"name": "Google",
"value": "1234567"
},
"datePosted": "2024-01-18",
"validThrough": "2024-03-18T00:00",
"employmentType": "CONTRACTOR",
"hiringOrganization": {
"@type": "Organization",
"name": "Google",
"sameAs": "https://www.google.com",
"logo": "https://www.example.com/images/logo.png"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"streetAddress": "1600 Amphitheatre Pkwy",
"addressLocality": "Mountain View",
"addressRegion": "CA",
"postalCode": "94043",
"addressCountry": "US"
}
},
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": {
"@type": "QuantitativeValue",
"value": 40.00,
"unitText": "HOUR"
}
}
}
</script>
</head>
<body></body>
</html>必須プロパティ
Google が求人検索に出すために 絶対に必要なプロパティは5つだけ。これが欠けるとリッチリザルト テストでエラーになります。
| プロパティ | 型 | 内容 |
|---|---|---|
datePosted | Date | 雇用主が最初に投稿した日付(ISO 8601) |
description | Text | HTML 形式での求人の詳細説明(職務・資格・スキル・業務時間・学歴/経験要件など) |
hiringOrganization | Organization | 採用する組織。会社名のみを name に入れる(住所等は混ぜない) |
jobLocation | Place | 実際の勤務地(求人を投稿した場所ではない)。addressCountry は必須 |
title | Text | 職務の名称(求人ページのタイトルではない、Software Engineer 等) |
特に間違えやすい点を3つ:
descriptionは HTML 形式にする必要があり、<br><p><ul><li>などが使える。<h1><strong><em>は無視されるが、ページ内に書いてあっても害はないdescriptionとtitleを 同じ文字列にしてはいけないtitleには求人コード・住所・日付・給与・会社名を 混ぜない。「*** 倉庫でのお仕事です!バス停のすぐ近く!***」のような装飾だらけのタイトルはスパム扱いされうる
hiringOrganization で 匿名募集(人材派遣会社の代理掲載など)を表現する場合は、name に文字列 confidential を入れます。
"hiringOrganization": {
"@type": "Organization",
"name": "confidential"
}推奨プロパティ
必須ではないが、入れると求人検索での見え方や絞り込み対応が良くなる代表格を整理。
| プロパティ | 型 | 内容 |
|---|---|---|
applicantLocationRequirements | AdministrativeArea | 在宅勤務時に応募者が所在する必要のある地域。リモート求人で実質必須 |
baseSalary | MonetaryAmount | 基本給。unitText は HOUR DAY WEEK MONTH YEAR のいずれか |
directApply | Boolean | このページから直接応募できるか(短いステップ・追加ログイン不要なら true) |
employmentType | Text | 雇用形態(複数指定可) |
identifier | PropertyValue | 採用側組織の中での求人 ID |
jobLocationType | Text | 完全リモート求人で TELECOMMUTE を指定。完全リモートなら 必須 |
validThrough | DateTime | 求人の有効期限。期限がある求人では 必須扱い |
employmentType の選択肢
公式が用意している雇用形態の値は以下の8つで、配列で複数指定できます。
"employmentType": ["FULL_TIME", "CONTRACTOR"]| 値 | 意味 |
|---|---|
FULL_TIME | フルタイム |
PART_TIME | パートタイム |
CONTRACTOR | 契約社員 |
TEMPORARY | 派遣社員 |
INTERN | インターンシップ |
VOLUNTEER | ボランティア |
PER_DIEM | 日雇い |
OTHER | その他 |
baseSalary の書き方(範囲指定も可能)
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "JPY",
"value": {
"@type": "QuantitativeValue",
"value": 5000000,
"unitText": "YEAR"
}
}"baseSalary": {
"@type": "MonetaryAmount",
"currency": "JPY",
"value": {
"@type": "QuantitativeValue",
"minValue": 4500000,
"maxValue": 6500000,
"unitText": "YEAR"
}
}雇用主以外(求人サイト側)が 概算で baseSalary を入れるのは禁止。実額が分からないなら省略するのが無難です。
directApply の判断基準
true と書ける条件は実質的に「応募までのステップが短いこと」。公式は次のいずれかが満たされる場合に直接応募と判断されるとしています。
- 求人ページ上で応募が完了する
- Google から到達後、何度もログイン・情報入力がない
- メール・電話・住所など、雇用主への直接的な連絡先が記載されている
応募までに別サイトを2〜3段挟む構成では directApply: false が現実的です。
リモートワーク(在宅勤務)求人のマークアップ
完全リモート求人を Google が「リモート」として認識するためには、次の3プロパティを 状況に応じて組み合わせる必要があります。
| プロパティ | 役割 |
|---|---|
jobLocationType | リモート可なら TELECOMMUTE を指定 |
applicantLocationRequirements | 応募者が所在する必要のある国・州 |
jobLocation | 物理的なオフィス(あれば) |
公式が示す3パターンを整理します。
パターンA: 完全リモート、ただし所在地は限定
特定オフィスへの出勤は不要、ただし応募者は USA 在住である必要がある場合。
"applicantLocationRequirements": {
"@type": "Country",
"name": "USA"
},
"jobLocationType": "TELECOMMUTE"パターンB: 物理オフィスもある、米国内ならリモートも可
デトロイトのオフィス勤務 or 米国内リモートのハイブリッド。
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "Detroit",
"addressRegion": "MI",
"addressCountry": "US"
}
},
"jobLocationType": "TELECOMMUTE"パターンC: 物理オフィス + 特定の州だけ在宅可
デトロイトのオフィス勤務 or ミシガン州 / テキサス州在住者のみリモート可。
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"streetAddress": "555 Clancy St",
"addressLocality": "Detroit",
"addressRegion": "MI",
"postalCode": "48201",
"addressCountry": "US"
}
},
"applicantLocationRequirements": [
{ "@type": "State", "name": "Michigan, USA" },
{ "@type": "State", "name": "Texas, USA" }
],
"jobLocationType": "TELECOMMUTE"注意点として、TELECOMMUTE を指定する求人は 完全にリモートでなければなりません。「一時的な在宅可」「交渉次第」「ハイブリッド前提」では使ってはいけない、と公式が明記しています。
学歴と経験のプロパティ(ベータ版)
2026年5月時点ではまだベータ扱いですが、educationRequirements と experienceRequirements を追加すると、Google 側で学歴・経験要件をより構造的に扱える可能性があります。
"educationRequirements": {
"@type": "EducationalOccupationalCredential",
"credentialCategory": "bachelor degree"
},
"experienceRequirements": {
"@type": "OccupationalExperienceRequirements",
"monthsOfExperience": 36
}credentialCategory で使える値:
| 値 | 意味 |
|---|---|
high school | 高校卒 |
associate degree | 準学士号 |
bachelor degree | 学士号 |
professional certificate | 認定資格 |
postgraduate degree | 大学院修了 |
学歴要件がない場合は no requirements、不明な場合はプロパティを そもそも追加しないのが正解。あいまいな値を入れて拾われ方が壊れるよりは黙る方が安全です。
経験について複雑な条件(「シェフ12ヶ月 または 副シェフ24ヶ月」など)を表現する場合、monthsOfExperience には 応募者が満たす必要のある最小の月数を入れる、と公式は説明しています。「または」なら12、「および」なら24です。
experienceInPlaceOfEducation を true にすると、「正式な学位がなくても経験で代替可」を表現できます。これを使うときは educationRequirements と experienceRequirements の両方を必ず指定する必要があります。
Next.js (App Router) での実装例
App Router では、各求人ページのコンポーネントから JSON-LD を直接出力するのが一番シンプルです。
import { notFound } from 'next/navigation';
import { getJob } from '@/lib/jobs';
type Props = { params: Promise<{ id: string }> };
export default async function JobPage({ params }: Props) {
const { id } = await params;
const job = await getJob(id);
if (!job) notFound();
const jsonLd = {
'@context': 'https://schema.org/',
'@type': 'JobPosting',
title: job.title,
description: job.descriptionHtml,
identifier: {
'@type': 'PropertyValue',
name: job.companyName,
value: job.id,
},
datePosted: job.postedAt,
validThrough: job.expiresAt,
employmentType: job.employmentTypes,
hiringOrganization: {
'@type': 'Organization',
name: job.companyName,
sameAs: job.companyUrl,
logo: job.companyLogoUrl,
},
jobLocation: {
'@type': 'Place',
address: {
'@type': 'PostalAddress',
streetAddress: job.address.street,
addressLocality: job.address.city,
addressRegion: job.address.region,
postalCode: job.address.postalCode,
addressCountry: job.address.country,
},
},
baseSalary: job.salary && {
'@type': 'MonetaryAmount',
currency: job.salary.currency,
value: {
'@type': 'QuantitativeValue',
minValue: job.salary.min,
maxValue: job.salary.max,
unitText: 'YEAR',
},
},
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<article>
<h1>{job.title}</h1>
<div dangerouslySetInnerHTML={{ __html: job.descriptionHtml }} />
</article>
</>
);
}ポイント:
<script type="application/ld+json">を Server Component から直接出力すれば SSR 時点で HTML に焼き込まれ、Googlebot が JS を実行できなくても確実に拾えるJSON.stringifyで出力すれば、null や undefined のフィールドは自動的に消える(Google は 空のキーを嫌う)- 値の整合性(ページに表示されている内容と JSON-LD の内容が一致していること)が コンテンツポリシー上の要件なので、求人本文との二重管理は避けて同じ DB から生成する
期限切れ求人の正しい消し方
「採用が決まったので求人を取り下げたい」場合の対応は、公式が3択を提示しています。
| 方法 | 内容 |
|---|---|
validThrough を過去にする | プロパティ自体は残し、日付だけ過去日に書き換える |
| ページごと削除 | 404 または 410 を返すようにする |
JobPosting 構造化データだけ削除 | 求人ページは残すが構造化データから外す |
そのうえで Indexing API で削除リクエストを通知するのが推奨フローです。これを怠り「期限切れの求人がいつまでも検索結果に出ている」状態を放置すると、Search Console から 手動による対策を受ける可能性があります。
POST https://indexing.googleapis.com/v3/urlNotifications:publish
{
"url": "https://example.com/jobs/12345",
"type": "URL_UPDATED" // 削除なら URL_DELETED
}コンテンツポリシーの押さえどころ
JobPosting では 構造化データの一般ガイドラインに加えて、求人特有のコンテンツポリシーがあります。違反すると検索結果から落ちる/手動対策の対象になります。
主な違反パターン:
- 無関係なコンテンツ: 求人リスト(一覧)ページに
JobPostingを貼る → NG。1件1ページの詳細にだけ貼る - 不完全なコンテンツ: 説明文がスカスカ
- 不当表示: 偽の職務、応募者情報収集が目的の求人、雇用主のなりすまし、勤務地の偽装
- 冒とく的・下品な表現
- 求人を装った広告 / アフィリエイト
- 期限切れの求人を残しっぱなし
- 応募方法が示されていない: 求人フェアへの招待だけ、ログインしないと詳細が見えない
- 募集再開を装い応募者データだけ集める
- 応募者からの支払いが必要
- キーワードの乱用: タイトルや説明に検索語を不自然に詰め込む
ローカルとしてやりがちな2つの落とし穴:
- 「掲載中だが実は募集していない」状態の放置
- ページ本文に書いていない給与をマークアップだけに書く(ページ内容と JSON-LD の不一致は明示的に違反)
よくある審査エラーと修正方法
Search Console から飛んでくる代表的なメッセージとその直し方を整理します。
| エラー | 原因 | 修正 |
|---|---|---|
| 「リスティング ページに個々の求人の構造化データを含めることはできません」 | 一覧ページに JobPosting を貼っている | 一覧から JobPosting を削除し、詳細ページにだけ残す |
| 「ページ上のコンテンツがページの構造化データと異なっています」 | 給与・勤務地・タイトルなどがページに書いていない | ページ本文に同じ情報を表示する/構造化データから外す |
| 「有効期限が切れた求人の JobPosting 構造化データ」 | validThrough 未設定または未来日のまま | 過去日に更新 or 構造化データを削除 or ページを 404 化 |
| 「求人ページで申し込みを送信できません」 | 応募手段がページにない | 応募ボタン・連絡先・面接予約手段を必ず提示 |
| 「ロゴが間違っている」 | ナレッジパネルと違うロゴが出る | hiringOrganization.logo に正しい URL を指定(幅:高さ比 0.75〜2.5) |
| 「求人の場所が実在しない」 | addressLocality addressRegion の値が認識できない | リッチリザルト テストで地域プレビューが正しく出るまで修正 |
修正後は必ず Search Console から再審査リクエストを送るのを忘れずに。
リッチリザルトテストと Search Console での監視
実装後の確認は3段構え:
- リッチリザルト テスト で URL を検証 → エラー0 を目指す
- Search Console の URL 検査ツールで「Google から見た HTML」を確認(JS で動的生成している場合は特に重要)
- Search Console の 求人情報リッチリザルト レポートで経時変化を監視
モニタリングのタイミング: ① 初回デプロイ後、② テンプレート変更後、③ 定期的(週次・月次)の3回。「有効な項目が減って・無効な項目が増えていない」状態を維持するのが目標です。
Google アナリティクスでのトラッキング
Google 求人検索からの流入を切り分けたい場合、応募 URL に 公式が定めた UTM パラメータを付けることが推奨されています。
?utm_campaign=google_jobs_apply
&utm_source=google_jobs_apply
&utm_medium=organicこれを応募ボタンの href に組み込んでおくと、GA4 のトラフィック ソースで Google 求人カードからの流入が一目で分かります。
ご利用いただける地域(2026年5月時点)
Google for Jobs は世界中で展開されていて、日本も対象です。地域ブロックでまとめると次のとおり。
| 地域 | 状況 |
|---|---|
| アジア | 日本・インド・インドネシア・台湾・タイ・ベトナム ほか16ヶ国 |
| ヨーロッパ | フランス・ドイツ・イギリス ほか14ヶ国 |
| 中東・北アフリカ | エジプト・サウジアラビア・UAE ほか15ヶ国 |
| 北米 | 全地域 |
| 南米 | 全地域 |
| サハラ以南アフリカ | 全地域 |
「在宅勤務求人の絞り込み」など機能の出方は 地域や時期で異なることが公式に明記されています。日本でも完全リモート求人として TELECOMMUTE を指定しておくと、対応が広がったタイミングで自然に拾われます。
まとめ
JobPostingの必須はdatePosted/description/hiringOrganization/jobLocation/titleの5つだけ。まずここを完璧に- 推奨プロパティの中でも
baseSalaryemploymentTypevalidThroughjobLocationTypeは実質必須に近い - 完全リモート求人は
jobLocationType: TELECOMMUTE+applicantLocationRequirementsのセットが正解。一時的・交渉次第のリモートには使わない - 学歴・経験の
educationRequirementsexperienceRequirementsはベータだが、書いておけば将来的な拡張に備えられる - 期限切れは
validThrough過去日 / 404 / 構造化データ削除 のいずれかで必ず終わらせる - ページ本文と JSON-LD の 内容一致が最重要のコンテンツポリシー
- 求人 URL では サイトマップより Indexing APIが推奨
- 応募リンクには 公式 UTM パラメータを付与して GA で計測
求人サイトは「動きが速く・期限が切れる・SEO 影響がデカい」ジャンルなので、構造化データの整備とともに、Indexing API・Search Console・GA4 をワンセットで運用する体制まで作って初めて回り始めます。実装より運用の方が長丁場なので、最初からテンプレートと監視を組み込んでおくのがおすすめです。