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

perf(v2): more performant gtag and analytics plugin #2070

Merged
merged 5 commits into from
Dec 1, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 1 addition & 47 deletions packages/docusaurus-plugin-google-analytics/src/analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,57 +5,11 @@
* LICENSE file in the root directory of this source tree.
*/

import siteConfig from '@generated/docusaurus.config';

const {themeConfig} = siteConfig;

export default (function() {
if (!themeConfig.googleAnalytics) {
return null;
}

const {trackingID} = themeConfig.googleAnalytics;
if (process.env.NODE_ENV === 'development' && !trackingID) {
console.warn(
'You specified the `googleAnalytics` object in `themeConfig` but the `trackingID` field was missing. ' +
'Please ensure this is not a mistake.',
);
if (typeof window === 'undefined') {
return null;
}

if (
process.env.NODE_ENV !== 'production' ||
!trackingID ||
typeof window === 'undefined'
) {
return null;
}

/* eslint-disable */
(function(i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
(i[r] =
i[r] ||
function() {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(
window,
document,
'script',
'https://www.google-analytics.com/analytics.js',
'ga',
);
/* eslint-enable */

window.ga('create', trackingID, 'auto');
window.ga('send', 'pageview');

return {
onRouteUpdate({location}) {
// Set page so that subsequent hits on this page are attributed
Expand Down
56 changes: 54 additions & 2 deletions packages/docusaurus-plugin-google-analytics/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,64 @@

const path = require('path');

module.exports = function() {
module.exports = function(context) {
const {siteConfig} = context;
const {themeConfig} = siteConfig;
const {googleAnalytics} = themeConfig || {};

if (!googleAnalytics) {
throw new Error(
`You need to specify 'googleAnalytics' object in 'themeConfig' with 'trackingId' field in it to use docusaurus-plugin-google-analytics`,
);
}

const {trackingID} = googleAnalytics;

if (!trackingID) {
throw new Error(
'You specified the `googleAnalytics` object in `themeConfig` but the `trackingID` field was missing. ' +
'Please ensure this is not a mistake.',
);
}
const isProd = process.env.NODE_ENV === 'production';
return {
name: 'docusaurus-plugin-google-analytics',

getClientModules() {
return [path.resolve(__dirname, './analytics')];
return isProd ? [path.resolve(__dirname, './analytics')] : [];
},

injectHtmlTags() {
if (!isProd) {
return {};
}
return {
headTags: [
{
tagName: 'link',
attributes: {
rel: 'preconnect',
href: 'https://www.google-analytics.com',
},
},
// https://developers.google.com/analytics/devguides/collection/analyticsjs/#alternative_async_tag
{
tagName: 'script',
innerHTML: `
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', '${trackingID}', 'auto');
ga('send', 'pageview');
`,
},
{
tagName: 'script',
attributes: {
async: true,
src: 'https://www.google-analytics.com/analytics.js',
},
},
],
};
},
};
};
44 changes: 6 additions & 38 deletions packages/docusaurus-plugin-google-gtag/src/gtag.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,16 @@

import siteConfig from '@generated/docusaurus.config';

const {themeConfig} = siteConfig;

export default (function() {
if (!themeConfig.gtag) {
return null;
}

const {trackingID} = themeConfig.gtag;
if (process.env.NODE_ENV === 'development' && !trackingID) {
console.warn(
'You specified the `gtag` object in `themeConfig` but the `trackingID` field was missing. ' +
'Please ensure this is not a mistake.',
);
return null;
}

if (
process.env.NODE_ENV !== 'production' ||
!trackingID ||
typeof window === 'undefined'
) {
if (typeof window === 'undefined') {
return null;
}

/* eslint-disable */
const $scriptEl = window.document.createElement('script');
$scriptEl.async = 1;
$scriptEl.src = `https://www.googletagmanager.com/gtag/js?id=${trackingID}`;
window.document.head.appendChild($scriptEl);

window.dataLayer = window.dataLayer || [];
function gtag() {
// Have to use `arguments` instead of spreading as there are
// other properties attached to it e.g. callee.
// The GA library requires usage of `arguments.
window.dataLayer.push(arguments);
}
// Expose globally.
window.gtag = gtag;
gtag('js', new Date());
gtag('config', trackingID);
/* eslint-enable */
const {
themeConfig: {
gtag: {trackingID},
},
} = siteConfig;

return {
onRouteUpdate({location}) {
Expand Down
64 changes: 62 additions & 2 deletions packages/docusaurus-plugin-google-gtag/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,72 @@

const path = require('path');

module.exports = function() {
module.exports = function(context) {
const {siteConfig} = context;
const {themeConfig} = siteConfig;
const {gtag} = themeConfig || {};

if (!gtag) {
throw new Error(
`You need to specify 'gtag' object in 'themeConfig' with 'trackingId' field in it to use docusaurus-plugin-google-gtag`,
);
}

const {trackingID} = gtag;

if (!trackingID) {
throw new Error(
'You specified the `gtag` object in `themeConfig` but the `trackingID` field was missing. ' +
'Please ensure this is not a mistake.',
);
}

const isProd = process.env.NODE_ENV === 'production';
return {
name: 'docusaurus-plugin-google-gtag',

getClientModules() {
return [path.resolve(__dirname, './gtag')];
return isProd ? [path.resolve(__dirname, './gtag')] : [];
},

injectHtmlTags() {
if (!isProd) {
return {};
}
return {
headTags: [
{
tagName: 'link',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we still need preconnect to https://www.google-analytics.com?

I see <script type="text/javascript" async="" src="https://www.google-analytics.com/analytics.js"></script> in the deploy preview's HTML which seems to be added in by the loaded gtag script. Is that why you do preconnect to google-analytics.com here? If so, it would be good to add a comment as it isn't obvious.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. because gtag automatically add google analytics script for you. So its better to preconnect

attributes: {
rel: 'preconnect',
href: 'https://www.google-analytics.com',
},
},
{
tagName: 'link',
attributes: {
rel: 'preconnect',
href: 'https://www.googletagmanager.com',
},
},
// https://developers.google.com/analytics/devguides/collection/gtagjs/#install_the_global_site_tag
{
tagName: 'script',
attributes: {
async: true,
src: `https://www.googletagmanager.com/gtag/js?id=${trackingID}`,
},
},
{
tagName: 'script',
innerHTML: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${trackingID}');`,
},
],
};
},
};
};