Skip to content

Improve PortalJS template's SEO features #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Jun 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
974340e
[seo][lg]: central SEO config file created
Datopian-Shreyas Jun 17, 2025
b779116
[seo][xs]: modified seo-config-file
Datopian-Shreyas Jun 17, 2025
92a0ae8
[seo][md]: added jsonLd for homepage
Datopian-Shreyas Jun 19, 2025
417d2eb
[seo][md]: added jsonLd for organization page
Datopian-Shreyas Jun 19, 2025
3ebfdd6
[seo][md]: added jsonLd for search page
Datopian-Shreyas Jun 19, 2025
61bf865
[seo][md]: added jsonLd for org individual page
Datopian-Shreyas Jun 19, 2025
3abf4c4
[seo][md]: added jsonLd for dataset page
Datopian-Shreyas Jun 19, 2025
7104cc2
[seo][md]: added jsonLd for groups page
Datopian-Shreyas Jun 19, 2025
e38930e
[seo][xs]: added jsonLd for groups page
Datopian-Shreyas Jun 19, 2025
41f9399
[seo][lg]: added jsonLd for groups page and resource page
Datopian-Shreyas Jun 19, 2025
a49b231
[seo][lg]: breadcrumbLD fixes
Datopian-Shreyas Jun 19, 2025
634245b
[seo][xs]: small fix
Datopian-Shreyas Jun 19, 2025
7ca5ed8
[seo][xxl]: improved and fixed the nextseo component
Datopian-Shreyas Jun 24, 2025
555341c
[seo][sm]:Handled undefined resource properties in JSON-LD.
Datopian-Shreyas Jun 24, 2025
0791451
[seo][xs]: small fix
Datopian-Shreyas Jun 24, 2025
dcf5c54
[seo][xs]: manifest icon fixes
Datopian-Shreyas Jun 26, 2025
1f13583
[seo][xs]: indidual org page fixes
Datopian-Shreyas Jun 26, 2025
67b66d0
[seo][xs]: added types for structured data
Datopian-Shreyas Jun 26, 2025
6968b97
[seo][xs]: Added null safety for organization property access and Add…
Datopian-Shreyas Jun 26, 2025
7f6f34b
[seo][xs]: updated next-seo
Datopian-Shreyas Jun 26, 2025
ec474a4
[seo][xs]: updated next-seo
Datopian-Shreyas Jun 26, 2025
15f6084
[seo][xs]: updated next-seo
Datopian-Shreyas Jun 26, 2025
b86d9f3
[seo][xs]: updated next-seo
Datopian-Shreyas Jun 26, 2025
7bdc681
[seo][xs]: title updation on org and groups
Datopian-Shreyas Jun 26, 2025
655456a
[seo][xs]: small fix
Datopian-Shreyas Jun 26, 2025
4227069
[seo][xs]: search page title changed
Datopian-Shreyas Jun 26, 2025
143c491
[seo][xs]: added default title
Datopian-Shreyas Jun 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions components/schema/DatasetPageStructuredData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import nextSeoConfig, { imageUrl, siteTitle, url } from "@/next-seo.config";
import { Dataset } from "@portaljs/ckan";
import { BreadcrumbJsonLd, LogoJsonLd, NextSeo, DatasetJsonLd } from "next-seo";

export function DatasetPageStructuredData({ dataset }: { dataset: Dataset }) {
const title = dataset.title || dataset.name
const ownerOrg = dataset?.organization?.name || "Organization"
const datasetUrl = `${url}/@${ownerOrg}/${dataset.name}`
const description = dataset.notes || "Dataset page of " + title

return (
<>
<LogoJsonLd
url={datasetUrl}
logo={`${url}/favicon.ico`}
/>
<NextSeo
canonical={datasetUrl}
title={`${title} | ${siteTitle}`}
description={description}
openGraph={{
url: datasetUrl,
title: `${title} | ${siteTitle}`,
description: description,
images: [
{
url: imageUrl,
alt: title,
width: 1200,
height: 627,
},
],
site_name: siteTitle,
}}
twitter={nextSeoConfig.twitter}
/>
<BreadcrumbJsonLd
itemListElements={[
{
position: 1,
name: 'Home',
item: url,
},
{
position: 2,
name: ownerOrg,
item: `${url}/@${ownerOrg}`,
},
{
position: 3,
name: title,
item: datasetUrl
},
]}
/>
<DatasetJsonLd
id={`${datasetUrl}#webpage`}
url={datasetUrl}
name={title}
description={description}
/>
<DatasetJsonLd
id={`${datasetUrl}#dataset`}
url={datasetUrl}
name={title}
description={description}
creator={{
'@type': 'Organization',
name: ownerOrg,
}}
keywords={dataset.tags?.map(tag => tag.name) || []}
license={dataset.license_title}
distribution={
dataset.resources?.map(res => ({
'@type': 'DataDownload',
encodingFormat: res.format,
contentUrl: res.url,
name: res.name,
})) || []
}
/>
</>
);
}
64 changes: 64 additions & 0 deletions components/schema/GroupIndividualPageStructuredData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import nextSeoConfig, { imageUrl, siteTitle, url } from "@/next-seo.config";
import { Group } from "@portaljs/ckan";
import { BreadcrumbJsonLd, LogoJsonLd, NextSeo, WebPageJsonLd } from "next-seo";

export function GroupIndividualPageStructuredData({ group }: { group: Group }) {
const title = group.title || group.name
const groupUrl = `${url}/groups/${group.name}`
const description = group.description || "Group page of " + title
const image = group.image_display_url || imageUrl

return (
<>
<LogoJsonLd
url={groupUrl}
logo={group.image_display_url || `${url}/favicon.ico`}
/>
<NextSeo
canonical={groupUrl}
title={`${title} | ${siteTitle}`}
description={description}
openGraph={{
url: groupUrl,
title: `${title} | ${siteTitle}`,
description,
images: [
{
url: image,
alt: title,
width: 1200,
height: 627,
},
],
site_name: siteTitle,
}}
twitter={nextSeoConfig.twitter}
/>
<BreadcrumbJsonLd
itemListElements={[
{
position: 1,
name: 'Home',
item: url,
},
{
position: 2,
name: 'Groups Page',
item: `${url}/groups`,
},
{
position: 3,
name: title,
item: groupUrl,
},
]}
/>
<WebPageJsonLd
id={`${groupUrl}#grouppage`}
url={groupUrl}
name={title}
description={description}
/>
</>
);
}
64 changes: 64 additions & 0 deletions components/schema/GroupPageStructuredData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import nextSeoConfig, { imageUrl, siteTitle, url } from "@/next-seo.config";
import { BreadcrumbJsonLd, LogoJsonLd, NextSeo, WebPageJsonLd, SiteLinksSearchBoxJsonLd } from "next-seo";

export function GroupPageStructuredData() {
const title = "Groups"
const description = "Groups page of " + siteTitle
return (
<>
<LogoJsonLd
url={`${url}/groups`}
logo={`${url}/favicon.ico`}
/>
<NextSeo
canonical={`${url}/groups`}
title={`${title} | ${siteTitle}`}
description={description}
openGraph={{
url: `${url}/groups`,
title: `${title} | ${siteTitle}`,
description: description,
images: [
{
url: imageUrl,
alt: title,
width: 1200,
height: 627,
},
],
site_name: siteTitle,
}}
twitter={nextSeoConfig.twitter}
/>
<BreadcrumbJsonLd
itemListElements={[
{
position: 1,
name: 'Home',
item: url,
},
{
position: 2,
name: 'Groups Page',
item: `${url}/groups`,
},
]}
/>
<WebPageJsonLd
id={`${url}/groups#webpage`}
url={`${url}/groups`}
name={title}
description={description}
/>
<SiteLinksSearchBoxJsonLd
url={`${url}/groups`}
potentialActions={[
{
target: `${url}/groups`,
queryInput: "search_term_string"
},
]}
/>
</>
);
}
41 changes: 41 additions & 0 deletions components/schema/HomePageStructuredData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import nextSeoConfig, { description, siteTitle, title, url } from "@/next-seo.config";
import { BreadcrumbJsonLd, LogoJsonLd, NextSeo, WebPageJsonLd, SiteLinksSearchBoxJsonLd } from "next-seo";

export function HomePageStructuredData() {
return (
<>
<LogoJsonLd
url={url}
logo={`${url}/favicon.ico`}
/>
<NextSeo
title={`${siteTitle} | ${title}`}
{...nextSeoConfig}
/>
<BreadcrumbJsonLd
itemListElements={[
{
position: 1,
name: 'Home',
item: url,
},
]}
/>
<WebPageJsonLd
id={`${url}#webpage`}
url={url}
name={siteTitle}
description={description}
/>
<SiteLinksSearchBoxJsonLd
url={url}
potentialActions={[
{
target: `${url}/search?q={search_term_string}`,
queryInput: "required name=search_term_string",
},
]}
/>
</>
);
}
59 changes: 59 additions & 0 deletions components/schema/OrganizationIndividualPageStructuredData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import nextSeoConfig, { imageUrl, siteTitle, url } from "@/next-seo.config";
import { Organization } from "@portaljs/ckan";
import { BreadcrumbJsonLd, LogoJsonLd, NextSeo, WebPageJsonLd } from "next-seo";

export function OrganizationIndividualPageStructuredData({ org }: { org: Organization }) {
const encodedOrgName = encodeURIComponent(org.name || org.title || '')
const orgUrl = `${url}/@${encodedOrgName}`
const title = org.title || org.name
const description = org.description || "Organization page of " + title
const image = org.image_display_url || imageUrl
return (
<>
<LogoJsonLd
url={orgUrl}
logo={org.image_display_url || `${url}/favicon.ico`}
/>
<NextSeo
canonical={orgUrl}
title={`${title} | ${siteTitle}`}
description={description}
openGraph={{
url: orgUrl,
title: `${title} | ${siteTitle}`,
description: description,
images: [
{
url: image,
alt: title,
width: 1200,
height: 627,
},
],
site_name: siteTitle,
}}
twitter={nextSeoConfig.twitter}
/>
<BreadcrumbJsonLd
itemListElements={[
{
position: 1,
name: 'Home',
item: url,
},
{
position: 2,
name: title,
item: orgUrl,
},
]}
/>
<WebPageJsonLd
id={`${orgUrl}#webpage`}
url={orgUrl}
name={title}
description={description}
/>
</>
);
}
64 changes: 64 additions & 0 deletions components/schema/OrganizationPageStructuredData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import nextSeoConfig, { imageUrl, siteTitle, url } from "@/next-seo.config";
import { BreadcrumbJsonLd, LogoJsonLd, NextSeo, WebPageJsonLd, SiteLinksSearchBoxJsonLd } from "next-seo";

export function OrganizationPageStructuredData() {
const title = "Organizations"
const description = "Organizations page of " + siteTitle
return (
<>
<LogoJsonLd
url={`${url}/organizations`}
logo={`${url}/favicon.ico`}
/>
<NextSeo
canonical={`${url}/organizations`}
title={`${title} | ${siteTitle}`}
description={description}
openGraph={{
url: `${url}/organizations`,
title: `${title} | ${siteTitle}`,
description: description,
images: [
{
url: imageUrl,
alt: title,
width: 1200,
height: 627,
},
],
site_name: siteTitle,
}}
twitter={nextSeoConfig.twitter}
/>
<BreadcrumbJsonLd
itemListElements={[
{
position: 1,
name: 'Home',
item: url,
},
{
position: 2,
name: 'Organizations Page',
item: `${url}/organizations`,
},
]}
/>
<WebPageJsonLd
id={`${url}/organizations#webpage`}
url={`${url}/organizations`}
name={title}
description={description}
/>
<SiteLinksSearchBoxJsonLd
url={`${url}/organizations`}
potentialActions={[
{
target: `${url}/organizations`,
queryInput: "search_term_string"
},
]}
/>
</>
);
}
Loading