Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Working example with NextJS #37

Open
jdwinall-tm opened this issue May 1, 2017 · 3 comments
Open

Working example with NextJS #37

jdwinall-tm opened this issue May 1, 2017 · 3 comments

Comments

@jdwinall-tm
Copy link

jdwinall-tm commented May 1, 2017

Do you have an example for a site that supports SSR? I am using NextJS and I am not able to limit importing the vendor/GoogleAnalytics.js class to only client side rendering. How do I replace the GoogleAnalyticsStub below to get this working?

metrics.config.js

import { ga } from 'client-config'
import GoogleAnalytics from '../lib/GoogleAnalytics'

const MetricsConfig = {
  vendors: [{
    name: 'Google Analytics',
    api: new GoogleAnalytics({
      trackingId: ga.tracking_id
    })
  }],
  pageViewEvent: 'pageLoad',
  pageDefaults: () => {
    return {
      environment: ga.environment,
      siteName: ga.siteName,
      timestamp: Date.now(),
      path: '/'
    }
  },
  debug: ga.debug
}

export default MetricsConfig

Layout.js

import React from 'react'
import pageLoadTracking from '../lib/pageLoadTracking'

const Layout = ({ children }) => (
  <Main>
    {children}
  </Main>
)

export default pageLoadTracking(Layout)

package.json

 "dependencies": {
    "above-the-fold-only-server-render": "^1.0.3",
    "analytics.js": "^2.9.1",
    "config": "^1.25.1",
    "express": "^4.15.2",
    "js-yaml": "^3.8.3",
    "mkdirp": "^0.5.1",
    "next": "^2.3.1",
    "next-routes": "^1.0.26",
    "prop-types": "^15.5.8",
    "react": "^15.5.4",
    "react-apollo": "^1.2.0",
    "react-dom": "^15.5.4",
    "react-ga": "^2.2.0",
    "react-gpt": "^0.2.4",
    "react-metrics": "^2.3.1",
    "react-no-ssr": "^1.1.0",
    "styled-components": "^1.4.5"
  },
  "devDependencies": {
    "babel-eslint": "^7.2.3",
    "babel-plugin-module-resolver": "^2.7.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "babel-register": "^6.24.1",
    "chai": "^3.5.0",
    "enzyme": "^2.8.2",
    "ignore-styles": "^5.0.1",
    "jsdom": "^9.12.0",
    "lighthouse": "^1.6.3",
    "mocha": "^3.2.0",
    "nightwatch": "^0.9.14",
    "phantomjs-prebuilt": "^2.1.14",
    "react-test-renderer": "^15.5.4",
    "selenium-server": "^3.3.1",
    "sinon": "^2.1.0",
    "standard": "^10.0.1"
  },

GoogleAnalytics.js

let analytics
if (process.browser) {
  analytics = require('analytics.js') // eslint-disable-line global-require
}

/**
 * Performs the tracking calls to Google Analytics.
 * Utilizing Segment IO Analytics Integration.
 *
 * @module GoogleAnalytics
 * @class
 * @internal
 */
class GoogleAnalytics {
  constructor (options = {}) {
    this.name = 'Google Analytics'
    this._loaded = false
    this.options = options
  }
  /**
   *
   * @method pageView
   * @param {String} eventName
   * @param {Object} params
   * @returns {Promise}
   * @internal
   */
  pageView (...args) {
    return this.track(...args)
  }
  user (userId) {
    return new Promise((resolve) => {
      this.userId = userId
      resolve({
        userId
      })
    })
  }
  /**
   *
   * @method track
   * @param {String} eventName
   * @param {Object} params
   * @returns {Promise}
   * @internal
   */
  track (eventName, params) {
    return new Promise((resolve, reject) => {
      this._load().then(() => {
        this._track(eventName, params)
        resolve({
          eventName,
          params
        })
      }).catch((error) => {
        console.error('GA: Failed to initialize', error)
        reject(error)
      })
    })
  }
  /**
   *
   * @method _track
   * @param {String} eventName
   * @param {Object} params
   * @protected
   */
  _track (eventName, params) {
    if (eventName === 'pageView') {
      analytics.page(params.category, params)
      return
    }
    analytics.track(eventName, params)
  }
  /**
   *
   * @method _load
   * @protected
   */
  _load () {
    return this._promise || (this._promise = new Promise((resolve) => {
      if (this._loaded) {
        resolve()
      } else {
        analytics.once('ready', () => {
          this._loaded = true
          resolve()
        })
        analytics.initialize({
          'Google Analytics': this.options
        })
      }
    }))
  }
}

export default GoogleAnalytics
@jamsea
Copy link
Contributor

jamsea commented May 11, 2017

@jdwinall-tm Importing the library on the server side shouldn't cause an issue, as long as you make sure it's not firing any events on the server side.

I think this might solve your issue: https://github.com/nfl/react-metrics#override-default-page-view-tracking specifically this chunk of code:

    componentDidMount() {
        const {value1, value2} = this.props;
        this.context.metrics.pageView({value1, value2});
    }

Placing the logic in componentDidMount will force react to run it on the client side instead of the server side. Let me know if you need any more info!

@jdwinall-tm
Copy link
Author

jdwinall-tm commented May 24, 2017

@jamsea Is there a way to implement this on a component that is not a "route handling" component?

My issues seems to be with GoogleAnalytics.js. The first line of this file includes analytics.js, which imports analytics.js on the server and the client.

@jdwinall-tm
Copy link
Author

jdwinall-tm commented May 31, 2017

@jamsea I updated the issue description to include my GoogleAnalytics.js file. Adding the following lines addressed my client errors on the server issue.

let analytics
if (process.browser) {
  analytics = require('analytics.js') // eslint-disable-line global-require
}

My only remaining issue is related to sending the active page when navigating between links with NextJS. When I view the real time content activity while browsing my dev site, my entry page reports correctly. However, when I click a link in the site, the page title updates but the active page stays the same (whatever the entry point to the application was).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants