From 525a58b707934ded259e0a1db468f39dfb80bd79 Mon Sep 17 00:00:00 2001 From: Ricardo Mota Date: Mon, 11 Dec 2023 15:04:46 +0000 Subject: [PATCH] feat(react): add properties on structure data organization feat(react): add properties on structure data organization Revert "fix(react|redux): commerce pages in ssr not working" This reverts commit 7bd944a5c3ab309f7e62e103b1fd14ad1b50fc60. --- .../structuredOrganization.fixtures.ts | 27 ++++++ .../__tests__/structuredOrganization.test.tsx | 58 ++++++++++++- .../schemas/schemaPotentialAction.ts | 41 +++++++++ .../structured-data/structuredArticle.ts | 36 ++++---- .../structured-data/structuredOrganization.ts | 86 +++++++++++++------ .../structured-data/structuredProduct.ts | 55 ++++++------ .../structuredProductListing.ts | 13 ++- .../structuredWebsiteSearch.ts | 27 +----- .../generateSchemaOrgProperty.test.ts | 28 ++++++ .../utils/generateSchemaOrgProperty.ts | 7 ++ packages/react/src/contents/utils/index.ts | 1 + 11 files changed, 281 insertions(+), 98 deletions(-) create mode 100644 packages/react/src/contents/structured-data/schemas/schemaPotentialAction.ts create mode 100644 packages/react/src/contents/utils/__tests__/generateSchemaOrgProperty.test.ts create mode 100644 packages/react/src/contents/utils/generateSchemaOrgProperty.ts diff --git a/packages/react/src/contents/structured-data/__tests__/__fixtures__/structuredOrganization.fixtures.ts b/packages/react/src/contents/structured-data/__tests__/__fixtures__/structuredOrganization.fixtures.ts index 3808109de..32bb33116 100644 --- a/packages/react/src/contents/structured-data/__tests__/__fixtures__/structuredOrganization.fixtures.ts +++ b/packages/react/src/contents/structured-data/__tests__/__fixtures__/structuredOrganization.fixtures.ts @@ -18,7 +18,11 @@ export const organization = { headPrefix: '', }, name: 'Organization', + legalName: 'Organization legal', url: 'http://www.farfetch.com', + description: 'Description', + urlTemplate: 'http://www.farfetch.com/shopping', + searchTitle: 'Search Title', logoUrl: 'http://www.farfetch.com/static/logo.jpg', address: { street: 'Street name', @@ -72,3 +76,26 @@ export const organizationResult = { areaServed: 'Europe', }, }; + +export const organizationResultWithLegalNameDescription = { + ...organizationResult, + legalName: 'Organization legal', + description: 'Description', +}; + +export const organizationResultWithPotentialAction = { + ...organizationResult, + potentialAction: { + '@type': 'SearchAction', + name: 'Search Title', + target: { + '@type': 'EntryPoint', + urlTemplate: 'http://www.farfetch.com/shopping{search_term_string}', + }, + 'query-input': { + '@type': 'PropertyValueSpecification', + valueRequired: 'True', + valueName: 'search_term_string', + }, + }, +}; diff --git a/packages/react/src/contents/structured-data/__tests__/structuredOrganization.test.tsx b/packages/react/src/contents/structured-data/__tests__/structuredOrganization.test.tsx index f1e09414e..d01bbe087 100644 --- a/packages/react/src/contents/structured-data/__tests__/structuredOrganization.test.tsx +++ b/packages/react/src/contents/structured-data/__tests__/structuredOrganization.test.tsx @@ -2,10 +2,24 @@ import { MockRenderScript, organization, organizationResult, + organizationResultWithLegalNameDescription, + organizationResultWithPotentialAction, } from './__fixtures__/index.js'; import structuredOrganization from '../structuredOrganization.js'; -const { metadata, name, url, logoUrl, address, contact, sameAs } = organization; +const { + metadata, + name, + url, + logoUrl, + address, + contact, + sameAs, + legalName, + description, + urlTemplate, + searchTitle, +} = organization; describe('structuredOrganization', () => { it('should correctly generate JSON-LD for a Organization', () => { @@ -23,4 +37,46 @@ describe('structuredOrganization', () => { MockRenderScript(JSON.stringify(organizationResult)), ); }); + + it('should correctly generate JSON-LD for a Organization with legal name and description', () => { + const renderStructuredOrganization = structuredOrganization( + metadata, + name, + url, + logoUrl, + address, + contact, + sameAs, + undefined, + legalName, + description, + ); + + expect(renderStructuredOrganization).toEqual( + MockRenderScript( + JSON.stringify(organizationResultWithLegalNameDescription), + ), + ); + }); + + it('should correctly generate JSON-LD for a Organization with potential action', () => { + const renderStructuredOrganization = structuredOrganization( + metadata, + name, + url, + logoUrl, + address, + contact, + sameAs, + undefined, + undefined, + undefined, + searchTitle, + urlTemplate, + ); + + expect(renderStructuredOrganization).toEqual( + MockRenderScript(JSON.stringify(organizationResultWithPotentialAction)), + ); + }); }); diff --git a/packages/react/src/contents/structured-data/schemas/schemaPotentialAction.ts b/packages/react/src/contents/structured-data/schemas/schemaPotentialAction.ts new file mode 100644 index 000000000..6500c05c9 --- /dev/null +++ b/packages/react/src/contents/structured-data/schemas/schemaPotentialAction.ts @@ -0,0 +1,41 @@ +import * as schemaProperties from './schemaProperties.js'; +import generateSchemaOrgProperty from '../../utils/generateSchemaOrgProperty.js'; +import type { CustomSearchAction } from '../../types/index.js'; +import type { SEOMetadata } from '@farfetch/blackout-client'; + +/** + * Generate a schema for Potential Action. + * + * @example + * ``` + * const potencialActioin = schemaPotentialAction(searchTitle, urlTemplate, metadata); + * ``` + * + * @param searchTitle - Website title. + * @param urlTemplate - Complete url to query on. + * @param metadata - SEO metadata for type WebsiteSearch on Homepage. + * + * @returns - An object with Potential Action JSON-LD structured data. + */ +const schemaPotentialAction = ( + searchTitle: string, + urlTemplate: string, + metadata: SEOMetadata, +): CustomSearchAction => ({ + '@type': schemaProperties.DEFAULT_TYPE_ACTION, + name: + generateSchemaOrgProperty('homepage:searchTitle', metadata) || searchTitle, + target: { + '@type': schemaProperties.DEFAULT_TYPE_TARGET, + urlTemplate: + generateSchemaOrgProperty('homepage:searchUrl', metadata) || + `${urlTemplate}{search_term_string}`, + }, + 'query-input': { + '@type': schemaProperties.DEFAULT_TYPE_INPUT, + valueRequired: 'True', + valueName: 'search_term_string', + }, +}); + +export default schemaPotentialAction; diff --git a/packages/react/src/contents/structured-data/structuredArticle.ts b/packages/react/src/contents/structured-data/structuredArticle.ts index 6b7f5cf30..58efb65de 100644 --- a/packages/react/src/contents/structured-data/structuredArticle.ts +++ b/packages/react/src/contents/structured-data/structuredArticle.ts @@ -1,7 +1,7 @@ import * as schemaProperties from './schemas/schemaProperties.js'; import { + generateSchemaOrgProperty, getCategories, - getMetatag, stripUrlSubfolder, } from '../utils/index.js'; import { renderScriptTag } from '../helpers/index.js'; @@ -62,50 +62,52 @@ const structuredArticle = ( publisher: Publisher, space?: number, ): ReactElement => { - const generateSchemaOrgProperty = (property: string) => - getMetatag(property, metadata?.metatags); - const ARTICLE: WithContext
= { '@context': schemaProperties.DEFAULT_CONTEXT, '@type': schemaProperties.DEFAULT_TYPE, - name: generateSchemaOrgProperty('og:title') || metadata?.title, + name: generateSchemaOrgProperty('og:title', metadata) || metadata?.title, headline: metadata?.h1 || title, description: - generateSchemaOrgProperty('og:description') || metadata?.description, - url: generateSchemaOrgProperty('og:url') || stripUrlSubfolder(url), + generateSchemaOrgProperty('og:description', metadata) || + metadata?.description, + url: + generateSchemaOrgProperty('og:url', metadata) || stripUrlSubfolder(url), mainEntityOfPage: { '@type': schemaProperties.DEFAULT_TYPE_WEBPAGE, '@id': url, }, datePublished: - generateSchemaOrgProperty('article:datePublished') || + generateSchemaOrgProperty('article:datePublished', metadata) || date?.publicationDate, dateModified: - generateSchemaOrgProperty('article:dateModified') || + generateSchemaOrgProperty('article:dateModified', metadata) || date?.modificationDate, publisher: { '@type': schemaProperties.DEFAULT_ORGANISATION, name: - generateSchemaOrgProperty('article:publisher:name') || publisher?.name, - url: generateSchemaOrgProperty('article:publisher:url') || publisher?.url, + generateSchemaOrgProperty('article:publisher:name', metadata) || + publisher?.name, + url: + generateSchemaOrgProperty('article:publisher:url', metadata) || + publisher?.url, logo: { '@type': schemaProperties.DEFAULT_IMAGE_OBJECT, url: - generateSchemaOrgProperty('article:publisher:logo') || + generateSchemaOrgProperty('article:publisher:logo', metadata) || publisher?.logo, }, }, author: { '@type': schemaProperties.DEFAULT_ORGANISATION, - name: generateSchemaOrgProperty('og:site_name') || author, + name: generateSchemaOrgProperty('og:site_name', metadata) || author, }, - articleBody: generateSchemaOrgProperty('article:body'), + articleBody: generateSchemaOrgProperty('article:body', metadata), articleSection: - generateSchemaOrgProperty('article:section') || + generateSchemaOrgProperty('article:section', metadata) || getCategories(breadcrumbs), image: - generateSchemaOrgProperty('article:image') || - generateSchemaOrgProperty('og:image') || + generateSchemaOrgProperty('article:image', metadata) || + generateSchemaOrgProperty('og:image', metadata) || image, keywords: metadata?.keywords ?? undefined, }; diff --git a/packages/react/src/contents/structured-data/structuredOrganization.ts b/packages/react/src/contents/structured-data/structuredOrganization.ts index ab97aa71d..bb2e98816 100644 --- a/packages/react/src/contents/structured-data/structuredOrganization.ts +++ b/packages/react/src/contents/structured-data/structuredOrganization.ts @@ -1,6 +1,7 @@ import * as schemaProperties from './schemas/schemaProperties.js'; -import { getMetatag } from '../utils/index.js'; import { renderScriptTag } from '../helpers/index.js'; +import generateSchemaOrgProperty from '../utils/generateSchemaOrgProperty.js'; +import schemaPotentialAction from './schemas/schemaPotentialAction.js'; import type { Address, Contact } from '../types/index.js'; import type { Organization, WithContext } from 'schema-dts'; import type { ReactElement } from 'react'; @@ -36,14 +37,18 @@ import type { SEOMetadata } from '@farfetch/blackout-client'; * * ``` * - * @param metadata - SEO metadata for type Organization on Homepage. - * @param name - Name of the Organization. - * @param url - Relative url of the page (location.pathname). - * @param logoUrl - Complete url for logotype. - * @param address - Full address information. - * @param contact - Full Contact information. - * @param sameAs - SameAs links of organization (e.g. Links to facebook and/or instagram). - * @param space - Add whitespace and indentation to the serialized output. + * @param metadata - SEO metadata for type Organization on Homepage. + * @param name - Name of the Organization. + * @param url - Relative url of the page (location.pathname). + * @param logoUrl - Complete url for logotype. + * @param address - Full address information. + * @param contact - Full Contact information. + * @param sameAs - SameAs links of organization (e.g. Links to facebook and/or instagram). + * @param space - Add whitespace and indentation to the serialized output. + * @param legalName - Legal name of the Organization. + * @param description - Description of the Organization. + * @param searchTitle - Website title (Use in combination with urlTemplate to include potentialAction property). + * @param urlTemplate - Complete url to query on. * * @returns - A script tag with Organization JSON-LD structured data. */ @@ -56,49 +61,78 @@ const structuredOrganization = ( contact: Contact, sameAs: string[], space?: number, + legalName?: string, + description?: string, + searchTitle?: string, + urlTemplate?: string, ): ReactElement => { - const generateSchemaOrgProperty = (property: string) => - getMetatag(property, metadata?.metatags); - const ORGANIZATION: WithContext = { '@context': schemaProperties.DEFAULT_CONTEXT, '@type': schemaProperties.DEFAULT_ORGANISATION, - name: generateSchemaOrgProperty('organization:name') || name, - url: generateSchemaOrgProperty('organization:url') || url, - logo: generateSchemaOrgProperty('organization:logo') || logoUrl, - sameAs: generateSchemaOrgProperty('organization:sameAS') || sameAs, + name: generateSchemaOrgProperty('organization:name', metadata) || name, + url: generateSchemaOrgProperty('organization:url', metadata) || url, + logo: generateSchemaOrgProperty('organization:logo', metadata) || logoUrl, + sameAs: + generateSchemaOrgProperty('organization:sameAS', metadata) || sameAs, address: { '@type': schemaProperties.DEFAULT_TYPE_ADDRESS, streetAddress: - generateSchemaOrgProperty('organization:streetAddress') || + generateSchemaOrgProperty('organization:streetAddress', metadata) || address?.street, addressLocality: - generateSchemaOrgProperty('organization:addressLocality') || + generateSchemaOrgProperty('organization:addressLocality', metadata) || address?.locality, addressRegion: - generateSchemaOrgProperty('organization:addressRegion') || + generateSchemaOrgProperty('organization:addressRegion', metadata) || address?.region, postalCode: - generateSchemaOrgProperty('organization:postalCode') || + generateSchemaOrgProperty('organization:postalCode', metadata) || address?.postalCode, addressCountry: - generateSchemaOrgProperty('organization:addressCountry') || + generateSchemaOrgProperty('organization:addressCountry', metadata) || address?.country, }, contactPoint: { '@type': schemaProperties.DEFAULT_TYPE_CONTACT_POINT, telephone: - generateSchemaOrgProperty('organization:telephone') || contact?.phone, + generateSchemaOrgProperty('organization:telephone', metadata) || + contact?.phone, contactType: - generateSchemaOrgProperty('organization:contactType') || contact?.type, - email: generateSchemaOrgProperty('organization:email') || contact?.email, + generateSchemaOrgProperty('organization:contactType', metadata) || + contact?.type, + email: + generateSchemaOrgProperty('organization:email', metadata) || + contact?.email, contactOption: - generateSchemaOrgProperty('organization:contactOption') || + generateSchemaOrgProperty('organization:contactOption', metadata) || contact?.option, areaServed: - generateSchemaOrgProperty('organization:areaServed') || + generateSchemaOrgProperty('organization:areaServed', metadata) || contact?.areaServed, }, + ...(legalName + ? { + legalName: + generateSchemaOrgProperty('organization:legalName', metadata) || + legalName, + } + : {}), + ...(description + ? { + description: + generateSchemaOrgProperty('organization:description', metadata) || + description, + } + : {}), + ...(searchTitle && urlTemplate + ? { + potentialAction: schemaPotentialAction( + searchTitle, + urlTemplate, + metadata, + ), + } + : {}), }; return renderScriptTag(ORGANIZATION, space); diff --git a/packages/react/src/contents/structured-data/structuredProduct.ts b/packages/react/src/contents/structured-data/structuredProduct.ts index 750df0f16..057e0aa69 100644 --- a/packages/react/src/contents/structured-data/structuredProduct.ts +++ b/packages/react/src/contents/structured-data/structuredProduct.ts @@ -1,5 +1,8 @@ import * as schemaProperties from './schemas/schemaProperties.js'; -import { getConditionSchemaOrg, getMetatag } from '../utils/index.js'; +import { + generateSchemaOrgProperty, + getConditionSchemaOrg, +} from '../utils/index.js'; import { renderScriptTag } from '../helpers/index.js'; import type { Product as ProductSchema, WithContext } from 'schema-dts'; import type { ReactElement } from 'react'; @@ -44,58 +47,62 @@ const structuredProduct = ( seller: string, space?: number, ): ReactElement => { - const generateSchemaOrgProperty = (property: string) => - getMetatag(property, metadata?.metatags); - const metaSeller = generateSchemaOrgProperty('product:seller'); + const metaSeller = generateSchemaOrgProperty('product:seller', metadata); const PRODUCT: WithContext = { '@context': schemaProperties.DEFAULT_CONTEXT, '@type': schemaProperties.DEFAULT_TYPE_PRODUCT, name: - generateSchemaOrgProperty('product:name') || - generateSchemaOrgProperty('og:title') || + generateSchemaOrgProperty('product:name', metadata) || + generateSchemaOrgProperty('og:title', metadata) || product.name, description: - generateSchemaOrgProperty('product:description') || - generateSchemaOrgProperty('og:description') || + generateSchemaOrgProperty('product:description', metadata) || + generateSchemaOrgProperty('og:description', metadata) || product.description, image: product.images?.map((image: StructuredProductImage, index: number) => - generateSchemaOrgProperty(`product:image:${index + 1}`) - ? generateSchemaOrgProperty(`product:image:${index + 1}`) + generateSchemaOrgProperty(`product:image:${index + 1}`, metadata) + ? generateSchemaOrgProperty(`product:image:${index + 1}`, metadata) : image.url, - ) || generateSchemaOrgProperty('og:image'), - sku: generateSchemaOrgProperty('product:sku') || product.sku, + ) || generateSchemaOrgProperty('og:image', metadata), + sku: generateSchemaOrgProperty('product:sku', metadata) || product.sku, productID: - generateSchemaOrgProperty('product:id') || product.id?.toString(), - mpn: generateSchemaOrgProperty('product:mpn') || product.mpn, - color: generateSchemaOrgProperty('product:color') || product.colorName, + generateSchemaOrgProperty('product:id', metadata) || + product.id?.toString(), + mpn: generateSchemaOrgProperty('product:mpn', metadata) || product.mpn, + color: + generateSchemaOrgProperty('product:color', metadata) || product.colorName, category: - generateSchemaOrgProperty('product:category') || product.lastCategory, + generateSchemaOrgProperty('product:category', metadata) || + product.lastCategory, brand: { '@type': schemaProperties.DEFAULT_BRAND_TYPE, - name: generateSchemaOrgProperty('product:brand') || product.brandName, + name: + generateSchemaOrgProperty('product:brand', metadata) || + product.brandName, }, offers: { '@context': schemaProperties.DEFAULT_CONTEXT, '@type': schemaProperties.DEFAULT_TYPE_OFFER, - url: generateSchemaOrgProperty('og:url') || product.url, + url: generateSchemaOrgProperty('og:url', metadata) || product.url, price: - generateSchemaOrgProperty('product:price:amount') || + generateSchemaOrgProperty('product:price:amount', metadata) || product.price?.includingTaxes, priceCurrency: - generateSchemaOrgProperty('product:price:currency') || + generateSchemaOrgProperty('product:price:currency', metadata) || product.currencyIsoCode, itemCondition: - getConditionSchemaOrg(generateSchemaOrgProperty('product:condition')) || - schemaProperties.NEW_CONDITION, - availability: generateSchemaOrgProperty('product:availability') + getConditionSchemaOrg( + generateSchemaOrgProperty('product:condition', metadata), + ) || schemaProperties.NEW_CONDITION, + availability: generateSchemaOrgProperty('product:availability', metadata) ? schemaProperties.IN_STOCK : (product?.quantity ?? 0) > 0 ? schemaProperties.IN_STOCK : schemaProperties.OUT_OF_STOCK, priceValidUntil: - generateSchemaOrgProperty('product:price:priceValidUntil') || + generateSchemaOrgProperty('product:price:priceValidUntil', metadata) || product.price?.priceValidUntil, ...((metaSeller || seller) && { seller: { diff --git a/packages/react/src/contents/structured-data/structuredProductListing.ts b/packages/react/src/contents/structured-data/structuredProductListing.ts index 6eade0f68..b71b5484f 100644 --- a/packages/react/src/contents/structured-data/structuredProductListing.ts +++ b/packages/react/src/contents/structured-data/structuredProductListing.ts @@ -1,6 +1,6 @@ import * as schemaProperties from './schemas/schemaProperties.js'; -import { getMetatag } from '../utils/index.js'; import { renderScriptTag } from '../helpers/index.js'; +import generateSchemaOrgProperty from '../utils/generateSchemaOrgProperty.js'; import type { ItemList, WithContext } from 'schema-dts'; import type { ReactElement } from 'react'; import type { SEOMetadata } from '@farfetch/blackout-client'; @@ -40,9 +40,6 @@ const structuredProductListing = ( url: string, space?: number, ): ReactElement => { - const generateSchemaOrgProperty = (property: string) => - getMetatag(property, metadata?.metatags); - const generateProductUrl = (slug: string) => { const initialUrl = url?.substring(0, url?.lastIndexOf('/')); @@ -53,7 +50,7 @@ const structuredProductListing = ( '@context': schemaProperties.DEFAULT_CONTEXT, '@type': schemaProperties.DEFAULT_ITEM_LIST, name: - generateSchemaOrgProperty('productsList:name') || + generateSchemaOrgProperty('productsList:name', metadata) || listing?.name || 'Products Listing', url: url, @@ -63,8 +60,10 @@ const structuredProductListing = ( '@type': schemaProperties.DEFAULT_LIST_ITEM, position: index + 1, name: - generateSchemaOrgProperty(`productsList:${product.id}:name`) || - product.name, + generateSchemaOrgProperty( + `productsList:${product.id}:name`, + metadata, + ) || product.name, url: product.slug ? generateProductUrl(product.slug) : undefined, }), ), diff --git a/packages/react/src/contents/structured-data/structuredWebsiteSearch.ts b/packages/react/src/contents/structured-data/structuredWebsiteSearch.ts index 3afc0fb21..de4abeea7 100644 --- a/packages/react/src/contents/structured-data/structuredWebsiteSearch.ts +++ b/packages/react/src/contents/structured-data/structuredWebsiteSearch.ts @@ -1,7 +1,7 @@ import * as schemaProperties from './schemas/schemaProperties.js'; -import { getMetatag } from '../utils/index.js'; import { renderScriptTag } from '../helpers/index.js'; -import type { CustomSearchAction } from '../types/index.js'; +import generateSchemaOrgProperty from '../utils/generateSchemaOrgProperty.js'; +import schemaPotentialAction from './schemas/schemaPotentialAction.js'; import type { ReactElement } from 'react'; import type { SEOMetadata } from '@farfetch/blackout-client'; import type { WebSite, WithContext } from 'schema-dts'; @@ -40,30 +40,11 @@ const structuredWebsiteSearch = ( urlTemplate: string, space?: number, ): ReactElement => { - const generateSchemaOrgProperty = (property: string) => - getMetatag(property, metadata?.metatags); - - const POTENTIAL_ACTION: CustomSearchAction = { - '@type': schemaProperties.DEFAULT_TYPE_ACTION, - name: generateSchemaOrgProperty('homepage:searchTitle') || searchTitle, - target: { - '@type': schemaProperties.DEFAULT_TYPE_TARGET, - urlTemplate: - generateSchemaOrgProperty('homepage:searchUrl') || - `${urlTemplate}{search_term_string}`, - }, - 'query-input': { - '@type': schemaProperties.DEFAULT_TYPE_INPUT, - valueRequired: 'True', - valueName: 'search_term_string', - }, - }; - const WEBSITE: WithContext = { '@context': schemaProperties.DEFAULT_CONTEXT, '@type': schemaProperties.DEFAULT_TYPE_WEBSITE, - url: generateSchemaOrgProperty('organization:url') || url, - potentialAction: POTENTIAL_ACTION, + url: generateSchemaOrgProperty('organization:url', metadata) || url, + potentialAction: schemaPotentialAction(searchTitle, urlTemplate, metadata), }; return renderScriptTag(WEBSITE, space); diff --git a/packages/react/src/contents/utils/__tests__/generateSchemaOrgProperty.test.ts b/packages/react/src/contents/utils/__tests__/generateSchemaOrgProperty.test.ts new file mode 100644 index 000000000..6fa973cbc --- /dev/null +++ b/packages/react/src/contents/utils/__tests__/generateSchemaOrgProperty.test.ts @@ -0,0 +1,28 @@ +import generateSchemaOrgProperty from '../generateSchemaOrgProperty.js'; + +const metadata = { + title: 'Title', + h1: 'H1', + canonicalUrl: 'Canonical Url', + keywords: 'Keywords', + description: 'Description', + headPrefix: 'Head Prefix', + metatags: [ + { + tagName: 'Tag mame', + propertyType: 'property', + propertyDescription: 'Description', + contentType: 'Content Type', + content: 'Content', + }, + ], +}; + +describe('generateSchemaOrgProperty', () => { + it('should return a string with categories divided by commas', () => { + const categories = generateSchemaOrgProperty('Description', metadata); + const result = 'Content'; + + expect(categories).toBe(result); + }); +}); diff --git a/packages/react/src/contents/utils/generateSchemaOrgProperty.ts b/packages/react/src/contents/utils/generateSchemaOrgProperty.ts new file mode 100644 index 000000000..4510a19d7 --- /dev/null +++ b/packages/react/src/contents/utils/generateSchemaOrgProperty.ts @@ -0,0 +1,7 @@ +import getMetatag from './getMetatag.js'; +import type { SEOMetadata } from '@farfetch/blackout-client/src/contents/types/seoMetadata.types.js'; + +const generateSchemaOrgProperty = (property: string, metadata: SEOMetadata) => + getMetatag(property, metadata?.metatags); + +export default generateSchemaOrgProperty; diff --git a/packages/react/src/contents/utils/index.ts b/packages/react/src/contents/utils/index.ts index 8b5f6dc32..caa03ef7e 100644 --- a/packages/react/src/contents/utils/index.ts +++ b/packages/react/src/contents/utils/index.ts @@ -8,4 +8,5 @@ export { default as sortContentType } from './sortContentType.js'; export { default as stripUrlSubfolder } from './stripUrlSubfolder.js'; export { default as getListingSeoMetadataParams } from './getListingSeoMetadataParams.js'; export { default as getProductSeoMetadataParams } from './getProductSeoMetadataParams.js'; +export { default as generateSchemaOrgProperty } from './generateSchemaOrgProperty.js'; export * from './seoMetadata.js';