0

I'm using gatsby to develop a website.

I want to use AtInternet to track my page views.

In their docs, they explain how to integrate the tracker with a React Website.

So first, I import the smarttag.js from their cdn in my html.js: import React from "react" import PropTypes from "prop-types" import { withPrefix } from 'gatsby'

export default class HTML extends React.Component {
  render() {
    return (
      <html {...this.props.htmlAttributes}>
        <head>
          <meta charSet="utf-8" />
          <meta httpEquiv="x-ua-compatible" content="ie=edge" />
          <meta
            name="viewport"
            content="width=device-width, initial-scale=1, shrink-to-fit=no"
          />
          {this.props.headComponents}
          <script type="text/javascript" src="//tag.aticdn.net/XXXXX/smarttag.js"></script>
        </head>
        <body {...this.props.bodyAttributes}>
          {this.props.preBodyComponents}
          <div
            key={`body`}
            id="___gatsby"
            dangerouslySetInnerHTML={{ __html: this.props.body }}
          />
          {this.props.postBodyComponents}


        </body>
      </html>
    )
  }
}

HTML.propTypes = {
  htmlAttributes: PropTypes.object,
  headComponents: PropTypes.array,
  bodyAttributes: PropTypes.object,
  preBodyComponents: PropTypes.array,
  body: PropTypes.string,
  postBodyComponents: PropTypes.array,
}

Note, that I tried to directly use the "classic" tracking script there, but it wouldn't push a new event when a user would navigate to a new page

Then, I create the Service in components/ATInternetService.js :

class ATInternetService {
  constructor() {
    this.tag = this.newTag({secure: true});
  }

  newTag() {
    try {
      return new ATInternet.Tracker.Tag();
    } catch(ex) {
      return {
        dispatch: () => ({}),
        page: { set: () => ({}) }
      };
    }
  }

  //@param info: {name: string, level2?: string, chapter1?: string, chapter2?: string, chapter3?: string, customObject?: any}
  sendPage(name) {
    this.tag.page.set(name);
    this.tag.dispatch();
  }
}    
export let tag = new ATInternetService();

Then, I create the component in /components/pushAT.js :

    import React from 'react' 
    import {tag} from '../components/ATInternetService'
    class PushAT extends React.Component {
        componentDidMount () {
            tag.sendPage({
                name: '',
            })
        }

        componentDidUpdate (prevProps) {
        // Figure out if the path changed
        if (this.props.path !== prevProps.path) {

            tag.sendPage({
                name: '',
            })
        } 
        }
    }
    export default PushAT

And when I use the component on my page, it says :

 error  'ATInternet' is not defined  no-undef

I used the componentDidMount and ComponentDidUpdate after reading this : Remount componentDidMount() by path.name

I think one of the easiest way to implement the tracker would be just pushing the script on each page change. But I'm still a beginner, and I'm not sure how to do it.

What would you recommend, please?

bonakor
  • 5
  • 4
  • Have you imported `ATInternet`? We can't see your imports in your first code snippet. – tombraider Jan 21 '19 at 16:05
  • I did not on this file, but I did import it in my html.js How should I construct my import line to import ATInternet, which is hosted on their CDN ? – bonakor Jan 21 '19 at 16:16
  • If the resource is coming from a CDN then you're correct to import it via HTML. Could you amend your question with your `html.js` file, or whatever you're using as the template for your HTML. – tombraider Jan 21 '19 at 16:23
  • I amended my question :) – bonakor Jan 21 '19 at 16:32
  • OK, so that all looks OK. As you're importing the file via a CDN in your HTML, the JS is going to be loaded into the `window` object. In your `ATInternetService.js` file, you need to be calling `new window.ATInternet.Tracking.Tag()`. Is your Gatsby application booting? Quick way to check if ATInternet has loaded correctly it's just to view the `window` object in your dev tools console. – tombraider Jan 21 '19 at 16:38
  • When adding import React from 'react', Gatsby stop complaining about AtInternet being undefined. But then, the site won't build because window is undefined, haha. I'm trying to find a fix, but if you have an idea, go for it! – bonakor Jan 21 '19 at 17:01
  • If that's the case, try `global.window` – tombraider Jan 21 '19 at 17:03
  • Same issue. Console says this : WebpackError: TypeError: k.render is not a function – bonakor Jan 21 '19 at 17:05
  • I just landed on this: https://www.gatsbyjs.org/docs/browser-apis/#onRouteUpdate Do you think it would be easier to use it ? – bonakor Jan 21 '19 at 17:08
  • That error isn't necessarily to do with your use of `global.window`. It's complaining that `render` isn't a function. Can you trace the error stack and find out what component is actually throwing that error? – tombraider Jan 21 '19 at 17:09
  • Okay, I think the error is coming from PushAT. Either that or ATInternetService. But in my console, in development mode, it says "React will try to recreate this component tree from scratch using the error boundary you provided, LocationProvider.", and the component is PushAT – bonakor Jan 21 '19 at 17:41
  • You’re missing a render method in that class. Add one in, even if it just returns null and see what happens. – tombraider Jan 21 '19 at 17:44
  • Okay. It did build. Yay \o/ And it seems to push an event each time the user changes page – bonakor Jan 21 '19 at 18:03
  • Hi. I have one last question. How could I push the location.pathname of the page as name of my tag? I tried name: {location.pathname} but it send an error – bonakor Jan 22 '19 at 09:35
  • `location.pathname` is located on the `window` object, so it's the same technique that we used earlier: `global.window.location.pathname` – tombraider Jan 22 '19 at 09:58
  • Ah yeah! Perfect. In the afternoon, I'll update my question to reflect what to do. Thanks for everything – bonakor Jan 22 '19 at 11:27
  • No problem at all :) – tombraider Jan 22 '19 at 11:31

1 Answers1

0

Sounds like you've resolved your issue, but I think you could also try dynamically importing (work out of the box with Gatsby) the ATInternetService module in componentDidMount.

componentDidMount () {
    import('../components/ATInternetService').then(({ tag }) => console.log(tag))
}

I think it should work with both gatsby develop & gatsby build && gatsby serve.

Derek Nguyen
  • 11,294
  • 1
  • 40
  • 64
  • Hey @bonakor! I suspect the error you get in the original question is cause because when you import { tag }, it try to run the constructor of the ATInternetService class, thus call ‘ATInternet’, which wasn’t defined in the scope at build time. By dynamically importing the tag instance in the ‘componentDidMount’ hook, it only call the code on the browser side, when ATInternet should already exist. – Derek Nguyen Jan 23 '19 at 02:11