From 5a32ac350dac17990adc50519f1dc888d62fd8e7 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Thu, 28 Sep 2017 20:49:43 +0300 Subject: [PATCH] LandingPage, SearchPage and ListingPage specify schema --- src/app.test.js | 7 +-- src/containers/LandingPage/LandingPage.js | 37 ++++++++++++- .../LandingPage/LandingPage.test.js | 2 + .../__snapshots__/LandingPage.test.js.snap | 33 +++++++++++- src/containers/ListingPage/ListingPage.js | 27 ++++++++++ .../__snapshots__/ListingPage.test.js.snap | 15 +++++- src/containers/SearchPage/SearchPage.js | 53 +++++++++++++++++-- src/containers/SearchPage/SearchPage.test.js | 1 + .../__snapshots__/SearchPage.test.js.snap | 12 ++++- src/translations/en.json | 4 ++ 10 files changed, 177 insertions(+), 14 deletions(-) diff --git a/src/app.test.js b/src/app.test.js index 5136e4e6..af70be51 100644 --- a/src/app.test.js +++ b/src/app.test.js @@ -34,11 +34,8 @@ describe('Application', () => { it('server renders pages that do not require authentication', () => { const urlTitles = { - '/': 'Landing page', - '/s': 'Search page: listings', - '/s/listings': 'Search page: listings', - '/s/filters': 'Search page: filters', - '/s/map': 'Search page: map', + '/': 'Book saunas everywhere', + '/s': 'Saunatime | search saunas everywhere', '/l/listing-title-slug/1234': 'Loading listing…', '/u/1234': 'Profile page with display name: 1234', '/login': 'Login', diff --git a/src/containers/LandingPage/LandingPage.js b/src/containers/LandingPage/LandingPage.js index 18350f56..a5f34d74 100644 --- a/src/containers/LandingPage/LandingPage.js +++ b/src/containers/LandingPage/LandingPage.js @@ -2,13 +2,17 @@ import React, { PropTypes } from 'react'; import { compose } from 'redux'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; +import { injectIntl, intlShape } from 'react-intl'; import { sendVerificationEmail } from '../../ducks/user.duck'; import { logout, authenticationInProgress } from '../../ducks/Auth.duck'; import { manageDisableScrolling, isScrollingDisabled } from '../../ducks/UI.duck'; import { PageLayout, HeroSection, Topbar } from '../../components'; import * as propTypes from '../../util/propTypes'; import { withFlattenedRoutes } from '../../util/contextHelpers'; +import config from '../../config'; +import facebookImage from '../../assets/saunatimeFacebook-1200x630.jpg'; +import twitterImage from '../../assets/saunatimeTwitter-600x314.jpg'; import css from './LandingPage.css'; export const LandingPageComponent = props => { @@ -20,6 +24,7 @@ export const LandingPageComponent = props => { currentUserHasOrders, flattenedRoutes, history, + intl, isAuthenticated, location, logoutError, @@ -31,14 +36,40 @@ export const LandingPageComponent = props => { sendVerificationEmailError, onResendVerificationEmail, } = props; + + // Schema for search engines (helps them to understand what this page is about) + // http://schema.org + // We are using JSON-LD format + const schemaTitle = intl.formatMessage({ id: 'LandingPage.schemaTitle' }); + const schemaDescription = intl.formatMessage({ id: 'LandingPage.schemaDescription' }); + const schemaImage = `${config.canonicalRootURL}/${facebookImage}`; + return ( + { @@ -135,6 +169,7 @@ const mapDispatchToProps = dispatch => ({ const LandingPage = compose( connect(mapStateToProps, mapDispatchToProps), + injectIntl, withRouter, withFlattenedRoutes )(LandingPageComponent); diff --git a/src/containers/LandingPage/LandingPage.test.js b/src/containers/LandingPage/LandingPage.test.js index 03dc2591..06ed8f05 100644 --- a/src/containers/LandingPage/LandingPage.test.js +++ b/src/containers/LandingPage/LandingPage.test.js @@ -1,4 +1,5 @@ import React from 'react'; +import { fakeIntl } from '../../util/test-data'; import { renderShallow } from '../../util/test-helpers'; import { LandingPageComponent } from './LandingPage'; import { RoutesProvider } from '../../components'; @@ -16,6 +17,7 @@ describe('LandingPage', () => { scrollingDisabled={false} authInProgress={false} currentUserHasListings={false} + intl={fakeIntl} isAuthenticated={false} onLogout={noop} onManageDisableScrolling={noop} diff --git a/src/containers/LandingPage/__snapshots__/LandingPage.test.js.snap b/src/containers/LandingPage/__snapshots__/LandingPage.test.js.snap index 5b61ce5b..06c60880 100644 --- a/src/containers/LandingPage/__snapshots__/LandingPage.test.js.snap +++ b/src/containers/LandingPage/__snapshots__/LandingPage.test.js.snap @@ -1,9 +1,40 @@ exports[`LandingPage matches snapshot 1`] = ` + title="LandingPage.schemaTitle" + twitterImages={ + Array [ + Object { + "height": 314, + "url": "saunatimeTwitter-600x314.jpg", + "width": 600, + }, + ] + }> : null; + const facebookImages = hasImages + ? currentListing.images.map(image => { + return image.attributes.sizes.find(i => i.name === 'facebook'); + }) + : []; + const twitterImages = hasImages + ? currentListing.images.map(image => { + return image.attributes.sizes.find(i => i.name === 'twitter'); + }) + : []; + const schemaImages = JSON.stringify(facebookImages.map(img => img.url)); + return ( {topbar}
diff --git a/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap b/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap index 22a69993..a8f4c9af 100644 --- a/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap +++ b/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap @@ -1,9 +1,22 @@ exports[`ListingPage matches snapshot 1`] = ` + title="listing1 title 55" + twitterImages={Array []}> { + const title = l.attributes.title; + const pathToItem = createResourceLocatorString('ListingPage', flattenedRoutes, { + id: l.id.uuid, + slug: createSlug(title), + }); + return { + '@type': 'ListItem', + position: i, + url: `${config.canonicalRootURL}${pathToItem}`, + name: title, + }; + }); + const schemaMainEntity = JSON.stringify({ + '@type': 'ItemList', + name: address, + itemListOrder: 'http://schema.org/ItemListOrderAscending', + itemListElement: schemaListings, + }); + // N.B. openMobileMap button is sticky. // For some reason, stickyness doesn't work on Safari, if the element is