I am trying to add Google Analytics to a React Web Application.
I know how to do it in HTML/CSS/JS sites and I have integrated it in an AngularJS app too. But, I'm not quite sure how to go about it when it comes to react.
With HTML/CSS/JS, I had just added it to every single page.
What I had done with AngularJS was adding GTM and GA script to index.html and added UA-labels to the HTML divs (and buttons) to get clicks.
How can I do that with React?
Please help!
Update: Feb 2019
As I saw that this question is being searched a lot, I decided to expand my explanation.
To add Google Analytics to React, I recommend using React-GA.
Add by running:
npm install react-ga --save
Initialization:
In a root component, initialize by running:
import ReactGA from 'react-ga';
ReactGA.initialize('Your Unique ID');
To report page view:
ReactGA.pageview(window.location.pathname + window.location.search);
To report custom event:
ReactGA.event({
category: 'User',
action: 'Sent message'
});
More instructions can be found in the github repo
The best practice for this IMO is using react-ga.
Have a look at the github rep
If you prefer not to use a package this is how it can work in a react application.
Add the "gtag" in index.html
<!-- index.html -->
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "<GA-PROPERTYID>");
</script>
In the submit action of the login form, fire off the event
window.gtag("event", "login", {
event_category: "access",
event_label: "login"
});
Without using a package this is how I would do it:
In your index.js (in the render method):
{/* Global site tag (gtag.js) - Google Analytics */}
<script
async
src="https://www.googletagmanager.com/gtag/js?id=YOUR_TRACKING_ID"
/>
<script>{injectGA()}</script>
And outside the class:
const injectGA = () => {
if (typeof window == 'undefined') {
return;
}
window.dataLayer = window.dataLayer || [];
function gtag() {
window.dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'YOUR_TRACKING_ID');
};
One other great library that you can check is redux-beacon.
It gets integrated very easily with react/redux application and has a great documentation for it. ReactGA is good too but with redux-beacon, you won't clutter your app code with google analytics code as it works via its own middleware.
Escape the analytics code with dangerouslySetInnerHTML
First you have of course to share the header code to all pages, e.g. as asked at: React js do common header
Then, this Next.js answer https://stackoverflow.com/a/24588369/895245 gives a good working code that should also work outside of Next.js. It escapes the analytics code with dangerouslySetInnerHTML:
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-47867706-3"></script>
<script
dangerouslySetInnerHTML={{
__html: `window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-47867706-3', { page_path: window.location.pathname });
`,
}}
/>
where you should replace UA-47867706-3 with your own code.
This code is exactly the code that Google gives, but with the following modification: we added the:
{ page_path: window.location.pathname }
to gtag('config' for it to be able to get the visited path, since this is a JavaScript SPA.
This generates the desired output on the browser:
<script async="" src="https://www.googletagmanager.com/gtag/js?id=UA-47867706-3"></script><script>window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-47867706-3', { page_path: window.location.pathname });
</script>
The only other divergence from the exact code given by Google is the async="" vs async, but both of those are equivalent in HTML since it is a boolean attribute, see also: What's the proper value for a checked attribute of an HTML checkbox?
Escaping with dangerouslySetInnerHTML is necessary because otherwise React interprets the code inside script a JSX and that fails with:
Syntax error: Unexpected token, expected "}"
21 | <script>
22 | window.dataLayer = window.dataLayer || [];
> 23 | function gtag(){dataLayer.push(arguments);}
| ^
24 | gtag('js', new Date());
25 |
26 | gtag('config', 'UA-47867706-3');
I wish they would just automatically escape stuff inside script for us.
Finally to get page switches, you also have to track that with more code, see the Next.js answer mentioned above for an example.
Related: Adding script tag to React/JSX
Tested on react 17.0.2, next.js 10.2.2.
There are 2 types of Google Analytics properties: Universal Analytics (UA-xxxxxxxxx-x) which is deprecated with the end of life on 2023.07.01 and Google Analytics 4 property (G-xxxxxxxxxx) which is the replacement.
react-ga was popular for Universal Analytics but the maintainer doesn't plan to update it (related issues: 1, 2, 3) and it had maintenance issues (1). react-ga4 and ga-4-react popped up as replacements but since these are similar wrappers you're at the mercy of the maintainers to implement and support all functionality.
The simplest way to get started is to follow Google's guide: include gtag on the page and use it as window.gtag. This method works for both old and new tags and there's even TypeScript support via #types/gtag.js. The script can be loaded async as recommended.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- ... -->
<script
async
src="https://www.googletagmanager.com/gtag/js?id=G-xxxxxxxxxx" >
</script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-xxxxxxxxxx')
</script>
<!-- ... -->
</head>
<body>
<!-- ... -->
</body>
</html>
Keep in mind that Google Analytics does automatic page tracking, but this will not work for every use case. For example, hash and search parameter changes are not tracked. This can lead to a lot of confusion. For example, when using HashRouter or anchor links the navigation will not be tracked. To have full control over page view tracking you can disable automatic tracking. See for a detailed explanation: The Ultimate Guide to Google Analytics (UA & GA4) on React (Or Anything Else
Manual page tracking: https://stackoverflow.com/a/63249329/2771889
You can see this working in cra-typescript-starter where I'm also setting the tag from an env var.
I suggest embedding the Segment script into your index.html, use the analytics library that is accessible on the window object, and add tracking calls onto React’s event handlers:
export default class SignupButton extends Component {
trackEvent() {
window.analytics.track('User Signup');
}
render() {
return (
<button onClick={this.trackEvent}>
Signup with Segment today!
</button>
);
}
}
I’m the maintainer of https://github.com/segmentio/analytics-react. I recommend checking it out if you want to solve this problem by using one singular API to manage your customer data, and be able to integrate into any other analytics tool (we support over 250+ destinations) without writing any additional code. 🙂
Looking at google's site https://developers.google.com/analytics/devguides/collection/analyticsjs,
you could also add Google Analytics using this function:
const enableGA = () => {
!function(A,n,g,u,l,a,r){A.GoogleAnalyticsObject=l,A[l]=A[l]||function(){
(A[l].q=A[l].q||[]).push(arguments)},A[l].l=+new Date,a=n.createElement(g),
r=n.getElementsByTagName(g)[0],a.src=u,r.parentNode.insertBefore(a,r)
}(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-X');
ga('send', 'pageview');
}
This way you don't need an external library, and it's pretty quick to setup.
I have to show jwplayer in a popup, for popups I am using ngDialog(angular), code for ngDialog is below:
$scope.showVideoPlayerPopup = function(video_path)
{
$scope.ngDialog = ngDialog;
ngDialog.open({
animation: true,
scope:$scope,
template:'<div id="video_popup"></div>',
plain: true,
//className: 'ngdialog-theme-default',
closeByDocument: true
//backdrop : 'static'
});
playVideo(video_path);
}
play video function called above contains code for jwplayer, which is below:
<script>
function playVideo(video_path)
{
jwplayer("video_popup").setup({
file: video_path,
width: "600px",
height: "600px",
stretching: "bestfit",
});
}
</script>
when I use the same jwplayer code for simple html code which is without popup it works fine but I try to put my html in popup it gives me below error:
Error: jwplayer(...).setup is not a function
update
Files I have included:
<script src="https://content.jwplatform.com/libraries/qAkRysIB.js"></script>
Ensure the jwplayer src is included (you likely already did but in case not:)
Update 11/2021
see the section Cloud-hosted on the documentation page Add a player library. This will require obtaining a JWPlayer account.
From your Player Downloads & Keys page, scroll down to the Cloud Hosted Player Libraries section.
In the Cloud Hosted Player Libraries section, select a Player Title from the dropdown menu.
Copy the Cloud Player Library Url.
Within the <head> of your page, copy and paste the URL to the player library.
<script src="{cloud_hosted_player_library_url}"></script>
Ensure that the panel has loaded before calling the setup function. One way to do this is to register an event listener for ngDialog.opened from the ngDialog (see the Events section of the ngDialog readme):
$scope.$on('ngDialog.opened', function (e, $dialog) {
playVideo();
});
Yes...because your div tag with id "current_video_path" has to be there in DOM before jwplayer(...).setup script can work...May be you can add some delay using $timeout or setTimeout so it will have enough time to render div in popup before this script can wrok..
I am trying to load these scripts
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.7/angular.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.7/angular-sanitize.min.js"></script>
in ionic framework to load/render emoticons using emoji.min.js
The emoticons renders very well when I build a separate app not on ionic to demo it. But immediately I integrate it into ionic app, it freezes.
This is the github url for the project
https://github.com/sagardalal21/AngularEmoji-IonicApp
To run the project, kindly open command prompt and type ionic serve
Kindly assist!
EMOJIS IN ANGULAR AND IONIC by pookdeveloper
EMOJIS IN ANGULAR AND IONIC
To show emjois in angular or ionic you can try this:
Create a service to call a json with all emojis, you can finde the emojis in this page:
https://raw.githubusercontent.com/dzfweb/nativescript-emoji/master/emoji.database.ts
emojis(): any {
return this.http.get('assets/data/emoji.json')
.map((res: any) => res.json());
}
Call the service:
/* CALL SERVICE TO GET EMOJIS */
emoticonos() {
this.confData.emojis().subscribe((data: any) => {
console.log("EMOJIS", data);
this.emojis = data;
});
}
Print the emojis:
<ion-item-group *ngFor="let emoji of emojis">
{{emoji.unicode}}
</ion-item-group>
I'm using Angular Google Maps to implement a map and geo-location in my Ionic app. I do everything according to the docs, but the map isn't displaying (even though there isn't any console output showing errors).
Controller:
app.controller('panicController', ['$scope', '$cordovaGeolocation',
function($scope, $cordovaGeolocation) {
$scope.map = { center: { latitude: 45, longitude: -73 }, zoom: 8 };
}
]);
View:
<ion-view hide-nav-bar="true" ng-controller="panicController" class="panic-view">
<ion-content data-tap-disabled="true" class="padding">
<ui-gmap-google-map center='map.center' zoom='map.zoom'></ui-gmap-google-map>
</ion-content>
</ion-view>
SCSS:
.angular-google-map-container {
height: 100%;
}
When I run it, I just get a blank/empty white view. And my console output:
Any idea of what the issue could be?
maybe this example can help you._
nightly codepen
I used this example in my application too and I like the way.
Do you need to develop it this way?
Greetz,
Bernhard
Try removing the sensor parameter. But according to the docs, it should not affect the API's behavior. It looks like there's something else going on that shows you the white view.
From the Google Maps API Docs: https://developers.google.com/maps/documentation/javascript/error-messages
SensorNotRequired: The sensor parameter is no longer required for the
Google Maps JavaScript API. It won't prevent the Google Maps
JavaScript API from working correctly, but we recommend that you
remove the sensor parameter from the script element.
In my case the solution was to explicitly specify dependency to uiGmapgoogle-maps via module, so make sure uiGmapgoogle-mapsmodule is included:
var app = angular.module('ionicApp', ['ionic', 'uiGmapgoogle-maps']);
Demo
So I am building an Ionic / AngularJS app using Wistia player API. I finial tried and everything work right on browser test mode. But when compile onto iOs, it just show white screen. Here is the detail:
View - HTML page:
<!-- Wistia Embed -->
<div id="{{ 'wistia_' + mediaHashId }}" class="wistia_embed" style="width:398px;height:224px;" ng-if="mediaHashId"></div>
Controller:
$timeout(function() {
var wistiaEmbed = Wistia.embed($scope.mediaHashId, {
videoFoam: true,
playerColor: "3B97D3"
});
wistiaEmbed.bind("end", function () {
alert ("Video is finished");
});
}, 100);
So it load perfectly onto Chrome.
But when I compile it onto xcode and run it on my phone. It just show a white screen (with no JS error!)
SECOND OPTION: iframe - since iframe load okay on iOs (http://wistia.com/doc/player-api#using_iframes_and_the_player_api).
The second option is attach wistiaApi onto an iframe. But the code does not work.
View - HTML page:
<div class="video-container">
<iframe id="wistia_player" ng-src="{{ mediaHashId | wistiaEmbedUrl }}" allowtransparency="true" frameborder="0" scrolling="no" class="wistia_embed" name="wistia_embed" width="640" height="360"></iframe>
</div>
Controller:
$timeout(function() {
var wistiaEmbed = document.getElementById("wistia_player").wistiaApi;
console.log (wistiaEmbed);
wistiaEmbed.bind("end", function () {
alert ("Video is finished");
});
}, 100);
The wistiaEmbed console log an undefined.
And error log:
TypeError: Cannot read property 'bind' of undefined
at lesson-detail-ctrl.js:46
at ionic.bundle.js:24922
at completeOutstandingRequest (ionic.bundle.js:13604)
at ionic.bundle.js:13984
So clearly .wistiaApi does not work...
I do include this in my index.html:
I will love a AngularJS library like this https://github.com/brandly/angular-youtube-embed with Wistia Player...but no luck...
Wow, I've found the problem. This is actually a very common problem when building ionic apps on iOs and/or Android. When you include <script> tags in your index.html, always put the full http://.... instead of using just //.
In my case, I included the Wistia API via their official documentation like:
<script src="//fast.wistia.com/assets/external/E-v1.js"></script>
It works on browsers because browsers are smart. Devices are not as smart as browsers so by including the http like so:
<script src="https://fast.wistia.com/assets/external/E-v1.js"></script>
Solves it!