Skip to content

Commit

Permalink
Enhancement/issue 186 google analytics plugin (#190)
Browse files Browse the repository at this point in the history
* working example with testse

* error handling

* update GA script and specs and integrated into the website

* custom plugins page

* finish docs

* clean up package.json

* anonymous IP tracking

* add Google SEO meta tag
  • Loading branch information
thescientist13 authored Sep 11, 2019
1 parent 11800e7 commit 770e940
Show file tree
Hide file tree
Showing 16 changed files with 429 additions and 9 deletions.
9 changes: 8 additions & 1 deletion greenwood.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const googleAnalyticsPlugin = require('./packages/plugin-google-analytics/src/index');
const path = require('path');

const META_DESCRIPTION = 'A modern and performant static site generator supporting Web Component based development';
Expand All @@ -15,6 +16,12 @@ module.exports = {
{ property: 'og:image', content: 'https://s3.amazonaws.com/hosted.greenwoodjs.io/greenwood-logo.png' },
{ property: 'og:description', content: META_DESCRIPTION },
{ rel: 'shortcut icon', href: FAVICON_HREF },
{ rel: 'icon', href: FAVICON_HREF }
{ rel: 'icon', href: FAVICON_HREF },
{ name: 'google-site-verification', content: '4rYd8k5aFD0jDnN0CCFgUXNe4eakLP4NnA18mNnK5P0' }
],
plugins: [
...googleAnalyticsPlugin({
analyticsId: 'UA-147204327-1'
})
]
};
3 changes: 2 additions & 1 deletion nyc.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ module.exports = {
'packages/cli/src/lib/*.js',
'packages/cli/src/lifecycles/*.js',
'packages/cli/src/plugins/*.js',
'packages/cli/src/tasks/*.js'
'packages/cli/src/tasks/*.js',
'packages/plugin-*/src/*.js'
],

reporter: [
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
<!-- Error is a known issue: https://github.com/webcomponents/webcomponentsjs/issues/749 -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.0.2/custom-elements-es5-adapter.js"></script> -->

<%= htmlWebpackPlugin.options.hookAnalytics %>

<%= htmlWebpackPlugin.options.hookSpaIndexFallback %>
</head>

<body>

<eve-app></eve-app>

<%= htmlWebpackPlugin.options.hookAnalytics %>

<%= htmlWebpackPlugin.options.hookPolyfills %>

<!-- JavaScript polyfill FOR IE11 -->
Expand Down
43 changes: 43 additions & 0 deletions packages/plugin-google-analytics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# @greenwood/plugin-google-analytics

## Overview
A composite plugin for Greenwood for adding support for [Google Analytics](https://developers.google.com/analytics/) JavaScript tracker. For more information and complete docs about Greenwood, please visit the [Greenwood website](https://www.greenwoodjs.io/docs).

> This package assumes you already have `@greenwood/cli` installed.
## Installation
You can use your favorite JavaScript package manager to install this package.

_examples:_
```bash
# npm
npm -i @greenwood/plugin-google-analytics --save-dev

# yarn
yarn add @greenwood/plugin-google-analytics --dev
```

## Usage
Use this plugin in your _greenwood.config.js_ and simply pass in your Google Analytics ID, e.g. `UA-XXXXX`.

> As this is a composite plugin, you will need to spread the result.
```javascript
const googleAnalyticsPlugin = require('@greenwood/plugin-google-analytics');

module.exports = {
...

plugins: [
...googleAnalyticsPlugin({
analyticsId: 'UA-XXXXXX'
})
]
}
```

This will then add the Google Analytics [JavaScript tracker snippet](https://developers.google.com/analytics/devguides/collection/analyticsjs/) to your project's _index.html_.

### Options
- `analyticsId` (required) - Your Google Analytics ID
- `anonymous` (optional) - If tracking of IPs should be done anonymously. Defaults to `true`
18 changes: 18 additions & 0 deletions packages/plugin-google-analytics/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@greenwood/plugin-google-analytics",
"version": "0.3.6",
"description": "A composite plugin for Greenwood for adding support for Google Analytics.",
"repository": "https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-google-analytics",
"author": "Owen Buckley <[email protected]>",
"license": "MIT",
"main": "src/index.js",
"files": [
"src/"
],
"publishConfig": {
"access": "public"
},
"peerDependencies": {
"@greenwood/cli": "^0.3.6"
}
}
30 changes: 30 additions & 0 deletions packages/plugin-google-analytics/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = (options = {}) => {
const { analyticsId, anonymous } = options;

const validId = analyticsId && typeof analyticsId === 'string';
const trackAnon = typeof anonymous === 'boolean' ? anonymous : true;

if (!validId) {
throw new Error(`Error: analyticsId should be of type string. get "${typeof analyticsId}" instead.`);
}

return [{
type: 'index',
provider: () => {
return {
hookAnalytics: `
<script async src="https://www.googletagmanager.com/gtag/js?id=${analyticsId}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${analyticsId}', { 'anonymize_ip': ${trackAnon} });
gtag('config', '${analyticsId}');
</script>
`
};
}
}];
};
109 changes: 109 additions & 0 deletions packages/plugin-google-analytics/test/cases/default/default.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Use Case
* Run Greenwood with Google Analytics composite plugin with default options.
*
* Uaer Result
* Should generate a bare bones Greenwood build with certain plugins injected into index.html.
*
* User Command
* greenwood build
*
* User Config
* const googleAnalyticsPlugin = require('@greenwod/plugin-google-analytics');
*
* {
* plugins: [{
* ...googleAnalyticsPlugin({
* analyticsId: 'UA-123456-1'
* })
* }]
*
* }
*
* User Workspace
* Greenwood default (src/)
*/
const expect = require('chai').expect;
const { JSDOM } = require('jsdom');
const path = require('path');
const runSmokeTest = require('../../../../../test/smoke-test');
const TestBed = require('../../../../../test/test-bed');

describe('Build Greenwood With: ', async function() {
const LABEL = 'Google Analytics Plugin with default options and Default Workspace';
const mockAnalyticsId = 'UA-123456-1';

let setup;

before(async function() {
setup = new TestBed();
this.context = setup.setupTestBed(__dirname);
});

describe(LABEL, function() {
before(async function() {
await setup.runGreenwoodCommand('build');
});

runSmokeTest(['public', 'index', 'not-found', 'hello'], LABEL);

describe('Initialization script at the end of the <body> tag', function() {
let inlineScript;

beforeEach(async function() {
const dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, 'index.html'));
const scriptTags = dom.window.document.querySelectorAll('head script');

inlineScript = Array.prototype.slice.call(scriptTags).filter(script => {
return !script.src;
});

});

it('should be one inline <script> tag', function() {
expect(inlineScript.length).to.be.equal(1);
});

it('should have the expected code with users analyicsId', function() {
const expectedContent = `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${mockAnalyticsId}', { 'anonymize_ip': true });
gtag('config', '${mockAnalyticsId}');
`;

expect(inlineScript[0].textContent).to.contain(expectedContent);
});
});

describe('Tracking script at the end of the <body> tag', function() {
let trackingScript;

beforeEach(async function() {
const dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, 'index.html'));
const scriptTags = dom.window.document.querySelectorAll('head script');

trackingScript = Array.prototype.slice.call(scriptTags).filter(script => {
return script.src === `https://www.googletagmanager.com/gtag/js?id=${mockAnalyticsId}`;
});
});

it('should have one <script> tag for loading the Google Analytics tracker', function() {
expect(trackingScript.length).to.be.equal(1);
});

it('should be an async <script> tag for loading the Google Analytics tracker', function() {
const isAsync = trackingScript[0].async !== null;

expect(isAsync).to.be.equal(true);
});
});
});

after(function() {
setup.teardownTestBed();
});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const googleAnalyticsPlugin = require('../../../src/index');

module.exports = {
plugins: [
...googleAnalyticsPlugin({
analyticsId: 'UA-123456-1'
})
]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Use Case
* Run Greenwood with Google Analytics composite plugin.
*
* Uaer Result
* Should generate an error when not passing in a valid analyticsId.
*
* User Command
* greenwood build
*
* User Config
* const googleAnalyticsPlugin = require('@greenwod/plugin-google-analytics');
*
* {
* plugins: [{
* ...googleAnalyticsPlugin()
* }]
*
* }
*
* User Workspace
* Greenwood default (src/)
*/
const expect = require('chai').expect;
const TestBed = require('../../../../../test/test-bed');

describe('Build Greenwood With: ', async function() {
let setup;

before(async function() {
setup = new TestBed();
this.context = setup.setupTestBed(__dirname);
});

describe('Google Analytics Plugin with a bad value for analyticsId', () => {
it('should throw an error that analyticsId must be a string', async () => {
try {
await setup.runGreenwoodCommand('build');
} catch (err) {
expect(err).to.contain('analyticsId should be of type string. get "undefined" instead.');
}
});
});

after(function() {
setup.teardownTestBed();
});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const googleAnalyticsPlugin = require('../../../src/index');

module.exports = {
plugins: [
...googleAnalyticsPlugin()
]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const googleAnalyticsPlugin = require('../../../src/index');

module.exports = {
plugins: [
...googleAnalyticsPlugin({
analyticsId: 'UA-123456-1',
anonymous: false
})
]
};
Loading

0 comments on commit 770e940

Please sign in to comment.