diff --git a/CHANGELOG.md b/CHANGELOG.md index 630dd4f4..af48dda9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Add `MicroData` component do `ProductPage`, so Google can have a detailed info on the Products. - Add the `SearchPage` GraphQL queries. +- Data layer intergration in the `ProductPage`. ## [0.3.0] - 2018-6-25 ### Added diff --git a/react/ProductPage.js b/react/ProductPage.js index 6443ab3b..3e43c6bb 100644 --- a/react/ProductPage.js +++ b/react/ProductPage.js @@ -1,21 +1,51 @@ import React, { Component, Fragment } from 'react' import PropTypes from 'prop-types' -import { graphql } from 'react-apollo' +import { graphql, compose } from 'react-apollo' import { ExtensionPoint } from 'render' import MicroData from './components/MicroData' + +import withDataLayer, { dataLayerProps } from './components/withDataLayer' import productQuery from './queries/productQuery.gql' class ProductPage extends Component { static contextTypes = { prefetchPage: PropTypes.func, } + static propTypes = { params: PropTypes.object, data: PropTypes.object, + ...dataLayerProps, + } + + pushToDataLayer = product => { + this.props.pushToDataLayer({ + event: 'productDetail', + ecommerce: { + detail: { + products: [{ + name: product.productName, + brand: product.brand, + category: product.categories.length > 0 ? product.categories[0] : undefined, + id: product.productId, + }], + }, + }, + }) } componentDidMount() { this.context.prefetchPage('store/home') + + if (!this.props.data.loading) { + this.pushToDataLayer(this.props.data.product) + } + } + + componentDidUpdate(prevProps) { + if (prevProps.data.loading && !this.props.data.loading) { + this.pushToDataLayer(this.props.data.product) + } } render() { @@ -23,20 +53,18 @@ class ProductPage extends Component { const { loading, variables, product } = data return ( -
-
- {!loading && ( - - - - - )} -
+
+ {!loading && ( + + + + + )}
) } @@ -50,6 +78,7 @@ const options = { }), } -export default graphql(productQuery, options)( - ProductPage -) +export default compose( + graphql(productQuery, options), + withDataLayer +)(ProductPage) diff --git a/react/StoreTemplate.js b/react/StoreTemplate.js index 1a0a0091..bb746d17 100644 --- a/react/StoreTemplate.js +++ b/react/StoreTemplate.js @@ -1,20 +1,33 @@ -import React, { Component, Fragment } from 'react' +import React, { Component } from 'react' import PropTypes from 'prop-types' import { ExtensionPoint } from 'render' +import { DataLayerProvider } from './components/withDataLayer' + export default class StoreTemplate extends Component { static propTypes = { children: PropTypes.element, } + pushToDataLayer = obj => { + window.dataLayer.push(obj) + } + render() { + window.dataLayer = window.dataLayer || [] + return ( - +
{this.props.children}
-
+ ) } } diff --git a/react/components/withDataLayer.js b/react/components/withDataLayer.js new file mode 100644 index 00000000..dd0e8913 --- /dev/null +++ b/react/components/withDataLayer.js @@ -0,0 +1,32 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' + +const { Consumer, Provider } = React.createContext({ + dataLayer: [], + pushToDataLayer: () => {}, +}) + +export { Provider as DataLayerProvider } + +export default function withDataLayer(WrappedComponent) { + return class DataLayer extends Component { + static displayName = + `DataLayer(${WrappedComponent.displayName || WrappedComponent.name})` + + render() { + return ( + + {context => ( + + )} + + ) + } + } +} + +export const dataLayerProps = { + dataLayer: PropTypes.array.isRequired, + pushToDataLayer: PropTypes.func.isRequired, +} +