From ed665befc78d1746f4f4b772a067b69cdef0b786 Mon Sep 17 00:00:00 2001 From: Corrie Sloot <35015915+corrie-sloot@users.noreply.github.com> Date: Wed, 27 Jul 2022 11:32:42 -0400 Subject: [PATCH] add dataset search (#1358) * First-class integration of market with Google Dataset Search. * Move schema to new SEO section * fix Unsafe usage of optional chaining --- .../@shared/Page/Seo/DatasetSchema.tsx | 77 +++++++++++++++++++ .../@shared/Page/{Seo.tsx => Seo/index.tsx} | 9 +++ src/components/Asset/AssetActions/index.tsx | 12 +++ 3 files changed, 98 insertions(+) create mode 100644 src/components/@shared/Page/Seo/DatasetSchema.tsx rename src/components/@shared/Page/{Seo.tsx => Seo/index.tsx} (88%) diff --git a/src/components/@shared/Page/Seo/DatasetSchema.tsx b/src/components/@shared/Page/Seo/DatasetSchema.tsx new file mode 100644 index 000000000..d5716065f --- /dev/null +++ b/src/components/@shared/Page/Seo/DatasetSchema.tsx @@ -0,0 +1,77 @@ +import { useAsset } from '@context/Asset' +import { useMarketMetadata } from '@context/MarketMetadata' +import useNetworkMetadata, { + filterNetworksByType +} from '@hooks/useNetworkMetadata' +import removeMarkdown from 'remove-markdown' + +const DatasetSchema = (): object => { + const { asset, isInPurgatory } = useAsset() + const { networksList } = useNetworkMetadata() + const { appConfig } = useMarketMetadata() + + const networksMain = filterNetworksByType( + 'mainnet', + appConfig.chainIdsSupported, + networksList + ) + + // only show schema on main nets + const isMainNetwork = networksMain.includes(asset?.chainId) + + const isDataset = asset?.metadata?.type === 'dataset' + + if (!asset || !isMainNetwork || !isDataset || isInPurgatory) return null + + let isDownloadable = false + if (asset?.services && Array.isArray(asset?.services)) { + for (const service of asset.services) { + if (service?.type === 'access') { + isDownloadable = true + break + } + } + } + + // https://developers.google.com/search/docs/advanced/structured-data/dataset + const datasetSchema = { + '@context': 'https://schema.org/', + '@type': 'Dataset', + name: asset?.metadata?.name, + description: removeMarkdown( + asset?.metadata?.description?.substring(0, 5000) || '' + ), + keywords: asset?.metadata?.tags, + datePublished: asset?.metadata?.created, + dateModified: asset?.metadata?.updated, + license: asset?.metadata?.license, + ...(asset?.accessDetails?.type === 'free' + ? { isAccessibleForFree: true } + : { + isAccessibleForFree: false, + paymentAccepted: 'Cryptocurrency', + currenciesAccepted: asset?.accessDetails?.baseToken?.symbol, + offers: { + '@type': 'Offer', + price: asset?.accessDetails?.price, + priceCurrency: asset?.accessDetails?.baseToken?.symbol + } + }), + creator: { + '@type': 'Organization', + name: asset?.metadata?.author + }, + ...(isDownloadable && { + distribution: [ + { + '@type': 'DataDownload', + encodingFormat: '' + } + ] + }) + } + + return datasetSchema +} + +export { DatasetSchema } diff --git a/src/components/@shared/Page/Seo.tsx b/src/components/@shared/Page/Seo/index.tsx similarity index 88% rename from src/components/@shared/Page/Seo.tsx rename to src/components/@shared/Page/Seo/index.tsx index 316893d9c..45a731298 100644 --- a/src/components/@shared/Page/Seo.tsx +++ b/src/components/@shared/Page/Seo/index.tsx @@ -3,6 +3,7 @@ import Head from 'next/head' import { isBrowser } from '@utils/index' import { useMarketMetadata } from '@context/MarketMetadata' +import { DatasetSchema } from './DatasetSchema' export default function Seo({ title, @@ -22,6 +23,8 @@ export default function Seo({ ? `${title} - ${siteContent?.siteTitle}` : `${siteContent?.siteTitle} — ${siteContent?.siteTagline}` + const datasetSchema = DatasetSchema() + return ( @@ -64,6 +67,12 @@ export default function Seo({ )} + + {datasetSchema && ( + + )} ) } diff --git a/src/components/Asset/AssetActions/index.tsx b/src/components/Asset/AssetActions/index.tsx index 26697f441..83fbabc55 100644 --- a/src/components/Asset/AssetActions/index.tsx +++ b/src/components/Asset/AssetActions/index.tsx @@ -64,6 +64,18 @@ export default function AssetActions({ ) : await getFileDidInfo(asset?.id, asset?.services[0]?.id, providerUrl) fileInfoResponse && setFileMetadata(fileInfoResponse[0]) + + // set the content type in the Dataset Schema + const datasetSchema = document.scripts?.namedItem('datasetSchema') + if (datasetSchema) { + const datasetSchemaJSON = JSON.parse(datasetSchema.innerText) + if (datasetSchemaJSON?.distribution[0]['@type'] === 'DataDownload') { + const contentType = fileInfoResponse[0]?.contentType + datasetSchemaJSON.distribution[0].encodingFormat = contentType + datasetSchema.innerText = JSON.stringify(datasetSchemaJSON) + } + } + setFileIsLoading(false) } catch (error) { LoggerInstance.error(error.message)