Skip to content

Commit

Permalink
fix: missing offers field in aggregateOffer (#769)
Browse files Browse the repository at this point in the history
* fix: missing offers field in aggregateOffer

This PR also includes a fix of not set fields show up issue which are images and manufacturer in product ld-json

* revert: readme

* chore(test): single aggregateOffer's offers object test added

* chore: aggregateOffer added in product schema
  • Loading branch information
hsynlms committed Jun 18, 2021
1 parent c8da29e commit 78789d2
Show file tree
Hide file tree
Showing 11 changed files with 473 additions and 31 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1769,10 +1769,11 @@ The property `aggregateOffer` is also available:

**Recommended properties**

| Property | Info |
| ------------ | ----------------------------------------------------------------------- |
| `highPrice` | The highest price of all offers available. Use a floating point number. |
| `offerCount` | The number of offers for the product. |
| Property | Info |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `highPrice` | The highest price of all offers available. Use a floating point number. |
| `offerCount` | The number of offers for the product. |
| `offers` | An offer to transfer some rights to an item or to provide a service. You can provide this as a single object, or an array of objects with the properties below. |

More info on the product data type can be found [here](https://developers.google.com/search/docs/data-types/product).

Expand Down
194 changes: 176 additions & 18 deletions cypress/e2e/jsonld.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,7 @@ describe('Validates JSON-LD For:', () => {
'@id': 'http://davesdeptstore.example.com',
name: "Dave's Department Store",
description: "Dave's latest department store in San Jose, now open",
url:
'http://www.example.com/store-locator/sl/San-Jose-Westgate-Store/1427',
url: 'http://www.example.com/store-locator/sl/San-Jose-Westgate-Store/1427',
telephone: '+14088717984',
address: {
'@type': 'PostalAddress',
Expand Down Expand Up @@ -502,6 +501,173 @@ describe('Validates JSON-LD For:', () => {
});
});

it('Product AggregateOffer and Offers (AggregateOffer ignored)', () => {
cy.visit('http://localhost:3000/product-jsonld/aggregateOfferAndOffers');
cy.get('head script[type="application/ld+json"]')
.should('have.length', 1)
.then(tags => {
const jsonLD = JSON.parse(tags[0].innerHTML);
expect(jsonLD).to.deep.equal({
'@context': 'https://schema.org/',
'@type': 'Product',
name: 'Executive Anvil',
offers: [
{
'@type': 'Offer',
price: '119.99',
priceCurrency: 'USD',
priceValidUntil: '2020-11-05',
itemCondition: 'https://schema.org/UsedCondition',
availability: 'https://schema.org/InStock',
url: 'https://www.example.com/executive-anvil',
seller: {
'@type': 'Organization',
name: 'Executive Objects',
},
},
{
'@type': 'Offer',
price: '139.99',
priceCurrency: 'CAD',
priceValidUntil: '2020-09-05',
itemCondition: 'https://schema.org/UsedCondition',
availability: 'https://schema.org/InStock',
url: 'https://www.example.ca/executive-anvil',
seller: {
'@type': 'Organization',
name: 'Executive Objects',
},
},
],
});
});
});

it('Product AggregateOffer', () => {
cy.visit('http://localhost:3000/product-jsonld/aggregateOffer');
cy.get('head script[type="application/ld+json"]')
.should('have.length', 1)
.then(tags => {
const jsonLD = JSON.parse(tags[0].innerHTML);
expect(jsonLD).to.deep.equal({
'@context': 'https://schema.org/',
'@type': 'Product',
name: 'Executive Anvil',
offers: {
'@type': 'AggregateOffer',
priceCurrency: 'USD',
lowPrice: '119.99',
highPrice: '139.99',
offerCount: '5',
offers: [
{
'@type': 'Offer',
price: '119.99',
priceCurrency: 'USD',
priceValidUntil: '2020-11-05',
itemCondition: 'https://schema.org/UsedCondition',
availability: 'https://schema.org/InStock',
url: 'https://www.example.com/executive-anvil',
seller: {
'@type': 'Organization',
name: 'Executive Objects',
},
},
{
'@type': 'Offer',
price: '139.99',
priceCurrency: 'CAD',
priceValidUntil: '2020-09-05',
itemCondition: 'https://schema.org/UsedCondition',
availability: 'https://schema.org/InStock',
url: 'https://www.example.ca/executive-anvil',
seller: {
'@type': 'Organization',
name: 'Executive Objects',
},
},
],
},
});
});
});

it('Product AggregateOffer (single)', () => {
cy.visit('http://localhost:3000/product-jsonld/aggregateOffer2');
cy.get('head script[type="application/ld+json"]')
.should('have.length', 1)
.then(tags => {
const jsonLD = JSON.parse(tags[0].innerHTML);
expect(jsonLD).to.deep.equal({
'@context': 'https://schema.org/',
'@type': 'Product',
name: 'Executive Anvil',
offers: {
'@type': 'AggregateOffer',
priceCurrency: 'USD',
lowPrice: '119.99',
highPrice: '139.99',
offerCount: '5',
offers: {
'@type': 'Offer',
price: '119.99',
priceCurrency: 'USD',
priceValidUntil: '2020-11-05',
itemCondition: 'https://schema.org/UsedCondition',
availability: 'https://schema.org/InStock',
url: 'https://www.example.com/executive-anvil',
seller: {
'@type': 'Organization',
name: 'Executive Objects',
},
},
},
});
});
});

it('Product Offers', () => {
cy.visit('http://localhost:3000/product-jsonld/offers');
cy.get('head script[type="application/ld+json"]')
.should('have.length', 1)
.then(tags => {
const jsonLD = JSON.parse(tags[0].innerHTML);
expect(jsonLD).to.deep.equal({
'@context': 'https://schema.org/',
'@type': 'Product',
name: 'Executive Anvil',
offers: [
{
'@type': 'Offer',
price: '119.99',
priceCurrency: 'USD',
priceValidUntil: '2020-11-05',
itemCondition: 'https://schema.org/UsedCondition',
availability: 'https://schema.org/InStock',
url: 'https://www.example.com/executive-anvil',
seller: {
'@type': 'Organization',
name: 'Executive Objects',
},
},
{
'@type': 'Offer',
price: '139.99',
priceCurrency: 'CAD',
priceValidUntil: '2020-09-05',
itemCondition: 'https://schema.org/UsedCondition',
availability: 'https://schema.org/InStock',
url: 'https://www.example.ca/executive-anvil',
seller: {
'@type': 'Organization',
name: 'Executive Objects',
},
},
],
});
});
});

it('Social Profile', () => {
cy.visit('http://localhost:3000/jsonld');
cy.get('head script[type="application/ld+json"]')
Expand Down Expand Up @@ -967,8 +1133,7 @@ describe('Validates JSON-LD For:', () => {
{
'@type': 'HowToStep',
name: 'Preheat',
text:
'Preheat the oven to 350 degrees F. Grease and flour a 9x9 inch pan.',
text: 'Preheat the oven to 350 degrees F. Grease and flour a 9x9 inch pan.',
url: 'https://example.com/party-coffee-cake#step1',
image: 'https://example.com/photos/party-coffee-cake/step1.jpg',
},
Expand Down Expand Up @@ -1069,8 +1234,7 @@ describe('Validates JSON-LD For:', () => {
mainEntity: {
'@type': 'Question',
name: 'How many ounces are there in a pound?',
text:
'I have taken up a new interest in baking and keep running across directions in ounces and pounds. I have to translate between them and was wondering how many ounces are in a pound?',
text: 'I have taken up a new interest in baking and keep running across directions in ounces and pounds. I have to translate between them and was wondering how many ounces are in a pound?',
answerCount: 3,
upvoteCount: 26,
dateCreated: '2016-07-23T21:11Z',
Expand All @@ -1092,8 +1256,7 @@ describe('Validates JSON-LD For:', () => {
suggestedAnswer: [
{
'@type': 'Answer',
text:
'Are you looking for ounces or fluid ounces? If you are looking for fluid ounces there are 15.34 fluid ounces in a pound of water.',
text: 'Are you looking for ounces or fluid ounces? If you are looking for fluid ounces there are 15.34 fluid ounces in a pound of water.',
dateCreated: '2016-11-02T21:11Z',
upvoteCount: 42,
url: 'https://example.com/question1#suggestedAnswer1',
Expand All @@ -1104,8 +1267,7 @@ describe('Validates JSON-LD For:', () => {
},
{
'@type': 'Answer',
text:
"I can't remember exactly, but I think 18 ounces in a lb. You might want to double check that.",
text: "I can't remember exactly, but I think 18 ounces in a lb. You might want to double check that.",
dateCreated: '2016-11-06T21:11Z',
upvoteCount: 0,
url: 'https://example.com/question1#suggestedAnswer2',
Expand Down Expand Up @@ -1411,17 +1573,15 @@ describe('Validates JSON-LD For:', () => {
{
'@type': 'HowToStep',
name: 'Preheat',
text:
'Preheat the oven to 350 degrees F. Grease and flour a 9x9 inch pan.',
text: 'Preheat the oven to 350 degrees F. Grease and flour a 9x9 inch pan.',
url: 'https://example.com/party-coffee-cake#step1',
image:
'https://example.com/photos/party-coffee-cake/step1.jpg',
},
{
'@type': 'HowToStep',
name: 'Mix dry ingredients',
text:
'In a large bowl, combine flour, sugar, baking powder, and salt.',
text: 'In a large bowl, combine flour, sugar, baking powder, and salt.',
url: 'https://example.com/party-coffee-cake#step2',
image:
'https://example.com/photos/party-coffee-cake/step2.jpg',
Expand Down Expand Up @@ -1506,17 +1666,15 @@ describe('Validates JSON-LD For:', () => {
{
'@type': 'HowToStep',
name: 'Preheat',
text:
'Preheat the oven to 350 degrees F. Grease and flour a 9x9 inch pan.',
text: 'Preheat the oven to 350 degrees F. Grease and flour a 9x9 inch pan.',
url: 'https://example.com/party-coffee-cake#step1',
image:
'https://example.com/photos/party-coffee-cake/step1.jpg',
},
{
'@type': 'HowToStep',
name: 'Mix dry ingredients',
text:
'In a large bowl, combine flour, sugar, baking powder, and salt.',
text: 'In a large bowl, combine flour, sugar, baking powder, and salt.',
url: 'https://example.com/party-coffee-cake#step2',
image:
'https://example.com/photos/party-coffee-cake/step2.jpg',
Expand Down
52 changes: 52 additions & 0 deletions cypress/schemas/product-schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,28 @@ const product100 = {
...aggregateRating100.schema,
see: aggregateRating100,
},
aggregateOffer: {
priceCurrency: {
type: 'string',
description: 'The product price currency',
},
lowPrice: {
type: 'string',
description: 'The lowest product price',
},
highPrice: {
type: 'string',
description: 'The highest product price',
},
offerCount: {
type: 'string',
description: 'The product offers count',
},
offers: {
...offers101.schema,
see: offers101,
},
},
offers: {
...offers101.schema,
see: offers101,
Expand Down Expand Up @@ -112,6 +134,36 @@ const product100 = {
ratingValue: '4.4',
reviewCount: '89',
},
aggregateOffer: {
priceCurrency: 'USD',
lowPrice: '119.99',
highPrice: '139.99',
offerCount: '5',
offers: [
{
price: '119.99',
priceCurrency: 'USD',
priceValidUntil: '2020-11-05',
itemCondition: 'https://schema.org/UsedCondition',
availability: 'https://schema.org/InStock',
url: 'https://www.example.com/executive-anvil',
seller: {
name: 'Executive Objects',
},
},
{
price: '139.99',
priceCurrency: 'CAD',
priceValidUntil: '2020-09-05',
itemCondition: 'https://schema.org/UsedCondition',
availability: 'https://schema.org/InStock',
url: 'https://www.example.ca/executive-anvil',
seller: {
name: 'Executive Objects',
},
},
],
},
offers: [
{
'@type': 'Offer',
Expand Down
15 changes: 15 additions & 0 deletions e2e/components/links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ const Links = () => (
<a>Carousel Recipe JSON-LD</a>
</Link>
</li>
<li>
<Link href="/product-jsonld/aggregateOffer">
<a>Product JSON-LD AggregateOffer</a>
</Link>
</li>
<li>
<Link href="/product-jsonld/offers">
<a>Product JSON-LD Offers</a>
</Link>
</li>
<li>
<Link href="/product-jsonld/aggregateOfferAndOffers">
<a>Product JSON-LD AggregateOffer and Offers</a>
</Link>
</li>
</ul>
);

Expand Down

0 comments on commit 78789d2

Please sign in to comment.