holidaycheck / react-google-tag-manager

This repository contains a react based implementation for Google's Tag Manager snippet.
MIT License
192 stars 31 forks source link

Fix noScriptAsReact #79

Open AdrienLemaire opened 6 years ago

AdrienLemaire commented 6 years ago

Here is, at least in my opinion, a cleaner way to write the google tag manager component:

import React, {Fragment} from "react";
import ReactDOM from "react-dom";
import PropTypes from "prop-types";
import gtmParts from "react-google-tag-manager";

const GoogleTagManager = ({gtmId, dataLayerName, events, previewVariables}) => {
  const gtm = gtmParts({id: gtmId, dataLayerName, events, previewVariables});

  const gtmNode = !window[dataLayerName]
    ? ReactDOM.createPortal(gtm.scriptAsReact(), document.head)
    : undefined;

  return (
    <Fragment>
      {gtmNode}
      {gtm.noScriptAsReact()}
    </Fragment>
  );
};

GoogleTagManager.propTypes = {
  gtmId: PropTypes.string.isRequired,
  dataLayerName: PropTypes.string,
  events: PropTypes.shape(),
  previewVariables: PropTypes.string,
};
GoogleTagManager.defaultProps = {
  dataLayerName: "dataLayer",
  events: {},
  previewVariables: "",
};

export default GoogleTagManager;

It would work if your scriptAsReact() method returned the javascript code as-is instead of a string which script content need to be retrieved and eval() (ie in the code above, replacing gtm.scriptAsReact() by the script would work fine). Would you mind adapting the method, or simply add another one to the GtmParts that'll only return the js code ?

Note that Google Tag Manager documentation recommends to set the script in the head element, not the body, which is why I'm using Fragment.

abbeyseto commented 5 years ago

i tried it this way, the scripts appears in the right places in the haed and body, but no event was firing from GTM and the debug console wasn't showing

AdrienLemaire commented 5 years ago

@abbeyseto works fine for me. Did you click on the "Preview" button from your Tag manager workspace ? The debug pane won't show without it (as far as I understand)

hhsadiq commented 5 years ago

@Fandekasp thanks for suggesting the cleaner way. Can you tell how is data passed to data layer. Looks like right now the component only accepts the datalayer name and events etc. But how to pass data to data layer? Using additionalEvents?

AdrienLemaire commented 5 years ago

@hhsadiq are you asking about how to use GTM ? You want to read the documentation: https://developers.google.com/tag-manager/devguide#events

hhsadiq commented 5 years ago

@Fandekasp Actually I am asking how to reference the data layer object. In google documentation they use dataLayer.push({...}), so it means that by including this package, the dataLayer object will be available in window. And to push data in dataLayer from non-render sections (lifecycle hooks, handlers, or stores etc) we should use window.dataLayer.push()?

It also means that your above suggested component will most probably be used once (if we are to use one data layer). And rest of the times we just reference the window.dataLayer, given that GTM is correctly loaded. Right?

AdrienLemaire commented 5 years ago

yes

hhsadiq commented 5 years ago

Awesome, thanks for the prompt reply.