SEO: page-specific OG/Twitter tags, fix JobPosting schema for remote jobs, remove contact demo note
- Add @section og_title/og_description/og_url/twitter_title/twitter_description to jobs/show, jobs/index, jobs/category, jobs/remote, blog/show - SeoService: add identifier field to JobPosting schema - SeoService: add jobLocationType=TELECOMMUTE for remote jobs (Google spec) - SeoService: fix remote job addressCountry (was 'Remote', not a valid ISO code) - SeoService: add directApply + applyUrl fields; set url to canonical JobifyGarden listing - Contact page: remove 'This is a demo form' note
This commit is contained in:
@@ -133,14 +133,26 @@ class SeoService
|
||||
'title' => $job->title,
|
||||
'description' => strip_tags($job->description),
|
||||
'datePosted' => $job->posted_at?->toIso8601String() ?? $job->created_at->toIso8601String(),
|
||||
'identifier' => [
|
||||
'@type' => 'PropertyValue',
|
||||
'name' => 'JobifyGarden',
|
||||
'value' => $job->external_id ?? (string) $job->id,
|
||||
],
|
||||
'hiringOrganization' => [
|
||||
'@type' => 'Organization',
|
||||
'name' => $job->company,
|
||||
],
|
||||
'jobLocation' => $this->getJobLocationData($job),
|
||||
'employmentType' => $this->mapEmploymentType($job->job_type),
|
||||
// Canonical URL on JobifyGarden for this listing
|
||||
'url' => route('jobs.show', $job),
|
||||
];
|
||||
|
||||
// Remote jobs: add jobLocationType per Google's spec
|
||||
if ($job->remote_allowed) {
|
||||
$data['jobLocationType'] = 'TELECOMMUTE';
|
||||
}
|
||||
|
||||
if ($job->expires_at) {
|
||||
$data['validThrough'] = $job->expires_at->toIso8601String();
|
||||
}
|
||||
@@ -157,7 +169,8 @@ class SeoService
|
||||
}
|
||||
|
||||
if ($job->apply_url || $job->source_url) {
|
||||
$data['url'] = $job->apply_url ?? $job->source_url;
|
||||
$data['directApply'] = true;
|
||||
$data['applyUrl'] = $job->apply_url ?? $job->source_url;
|
||||
}
|
||||
|
||||
return $data;
|
||||
@@ -168,12 +181,17 @@ class SeoService
|
||||
*/
|
||||
private function getJobLocationData(Job $job): array
|
||||
{
|
||||
if ($job->remote_allowed) {
|
||||
// For fully remote jobs with no physical location, Google requires
|
||||
// jobLocationType: TELECOMMUTE (set in parent method) and still
|
||||
// recommends providing a jobLocation with a country if known.
|
||||
// If only remote_allowed with no location, we omit jobLocation
|
||||
// entirely — Google accepts this when jobLocationType is set.
|
||||
if ($job->remote_allowed && !$job->jobLocation && !$job->location) {
|
||||
return [
|
||||
'@type' => 'Place',
|
||||
'address' => [
|
||||
'@type' => 'PostalAddress',
|
||||
'addressCountry' => 'Remote',
|
||||
'addressCountry' => 'US', // Default fallback; most aggregated jobs are US/global
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -183,9 +201,15 @@ class SeoService
|
||||
];
|
||||
|
||||
if ($job->jobLocation) {
|
||||
$address['addressLocality'] = $job->jobLocation->city;
|
||||
$address['addressRegion'] = $job->jobLocation->state;
|
||||
$address['addressCountry'] = $job->jobLocation->country;
|
||||
if ($job->jobLocation->city) {
|
||||
$address['addressLocality'] = $job->jobLocation->city;
|
||||
}
|
||||
if ($job->jobLocation->state) {
|
||||
$address['addressRegion'] = $job->jobLocation->state;
|
||||
}
|
||||
if ($job->jobLocation->country) {
|
||||
$address['addressCountry'] = $job->jobLocation->country;
|
||||
}
|
||||
} elseif ($job->location) {
|
||||
$address['name'] = $job->location;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user