├── .gitignore
├── README.md
├── demo.png
├── demo
└── src
│ └── index.js
├── nwb.config.js
├── package-lock.json
├── package.json
└── src
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | es
3 | lib
4 | demo/dist
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-analytics-widget
2 |
3 | [![npm package][npm-badge]][npm]
4 |
5 | Embed Google Analytics widgets in your React applications.
6 |
7 | - The `GoogleProvider` container ensure user is logged on analytics
8 | - The `GoogleDataChart` component display any [DataChart configuraton](https://developers.google.com/analytics/devguides/reporting/embed/v1/component-reference#datachart)
9 |
10 | 
11 |
12 | Demo : [https://revolunet.github.io/react-analytics-widget](https://revolunet.github.io/react-analytics-widget)
13 |
14 | ## Requirements
15 |
16 | You need to create a OAUTH client id in the [google developer console](https://console.developers.google.com/apis/credentials/oauthclient/960315238073-dv345fcj3tkikn506k9lrch73hk9259u.apps.googleusercontent.com?project=eastern-store-174123) and provide an [analytic view ID](https://ga-dev-tools.appspot.com/query-explorer/).
17 | Alternatively you can use server-side authentication tokens. You can find more info in this [example](https://ga-dev-tools.appspot.com/embed-api/server-side-authorization/).
18 |
19 | ### Note:
20 | If you provide values for both the `accessToken` and the `clientId` props, the latter will be ignored.
21 |
22 | Also, add the Google SDK at the top of your page
23 |
24 | ```js
25 | ;(function(w, d, s, g, js, fjs) {
26 | g = w.gapi || (w.gapi = {})
27 | g.analytics = {
28 | q: [],
29 | ready: function(cb) {
30 | this.q.push(cb)
31 | }
32 | }
33 | js = d.createElement(s)
34 | fjs = d.getElementsByTagName(s)[0]
35 | js.src = "https://apis.google.com/js/platform.js"
36 | fjs.parentNode.insertBefore(js, fjs)
37 | js.onload = function() {
38 | g.load("analytics")
39 | }
40 | })(window, document, "script")
41 | ```
42 |
43 | ## Usage
44 | ### OAUTH authentication
45 |
46 | ```js
47 |
48 | import { GoogleProvider, GoogleDataChart } from 'react-analytics-widget'
49 |
50 | const CLIENT_ID = 'x-x--x---x---x-xx--x-apps.googleusercontent.com';
51 |
52 | // graph 1 config
53 | const last30days = {
54 | reportType: "ga",
55 | query: {
56 | dimensions: "ga:date",
57 | metrics: "ga:pageviews",
58 | "start-date": "30daysAgo",
59 | "end-date": "yesterday"
60 | },
61 | chart: {
62 | type: "LINE",
63 | options: {
64 | // options for google charts
65 | // https://google-developers.appspot.com/chart/interactive/docs/gallery
66 | title: "Last 30 days pageviews"
67 | }
68 | }
69 | }
70 |
71 | // graph 2 config
72 | const last7days = {
73 | reportType: "ga",
74 | query: {
75 | dimensions: "ga:date",
76 | metrics: "ga:pageviews",
77 | "start-date": "7daysAgo",
78 | "end-date": "yesterday"
79 | },
80 | chart: {
81 | type: "LINE"
82 | }
83 | }
84 |
85 | // analytics views ID
86 | const views = {
87 | query: {
88 | ids: "ga:87986986"
89 | }
90 | }
91 |
92 | const Example = () => (
93 |
94 |
95 |
96 |
97 | )
98 | ```
99 |
100 | ### Server-side token authentication
101 |
102 | ```js
103 |
104 | import React, { Component } from 'react';
105 | import { GoogleProvider, GoogleDataChart } from 'react-analytics-widget'
106 |
107 | // graph 1 config
108 | const last30days = {
109 | reportType: "ga",
110 | query: {
111 | dimensions: "ga:date",
112 | metrics: "ga:pageviews",
113 | "start-date": "30daysAgo",
114 | "end-date": "yesterday"
115 | },
116 | chart: {
117 | type: "LINE",
118 | options: {
119 | // options for google charts
120 | // https://google-developers.appspot.com/chart/interactive/docs/gallery
121 | title: "Last 30 days pageviews"
122 | }
123 | }
124 | }
125 |
126 | // graph 2 config
127 | const last7days = {
128 | reportType: "ga",
129 | query: {
130 | dimensions: "ga:date",
131 | metrics: "ga:pageviews",
132 | "start-date": "7daysAgo",
133 | "end-date": "yesterday"
134 | },
135 | chart: {
136 | type: "LINE"
137 | }
138 | }
139 |
140 | // analytics views ID
141 | const views = {
142 | query: {
143 | ids: "ga:87986986"
144 | }
145 | }
146 |
147 | class Example extends Component {
148 | componentDidMount = () => {
149 | const request = new Request('https://yourserver.example/auth/ganalytics/getToken', {
150 | method: 'GET'
151 | });
152 | fetch(request)
153 | .then(response => response.json())
154 | .then(({ token }) => {
155 | this.setState({ token }); // TODO: handle errors
156 | });
157 | }
158 |
159 | render = () => (
160 |
161 |
162 |
163 |
164 | )
165 | }
166 | ```
167 |
168 | [npm-badge]: https://img.shields.io/npm/v/react-analytics-widget.png?style=flat-square
169 | [npm]: https://www.npmjs.org/package/react-analytics-widget
170 |
--------------------------------------------------------------------------------
/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/revolunet/react-analytics-widget/c0f529f71db4136abb34ab4c5d2777dc55d1dd29/demo.png
--------------------------------------------------------------------------------
/demo/src/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react"
2 | import { render } from "react-dom"
3 | import GithubCorner from 'react-github-corner';
4 |
5 | import { GoogleProvider, GoogleDataChart } from "../../src"
6 |
7 | ;(function(w, d, s, g, js, fjs) {
8 | g = w.gapi || (w.gapi = {})
9 | g.analytics = {
10 | q: [],
11 | ready: function(cb) {
12 | this.q.push(cb)
13 | }
14 | }
15 | js = d.createElement(s)
16 | fjs = d.getElementsByTagName(s)[0]
17 | js.src = "https://apis.google.com/js/platform.js"
18 | fjs.parentNode.insertBefore(js, fjs)
19 | js.onload = function() {
20 | g.load("analytics")
21 | }
22 | })(window, document, "script")
23 |
24 | const CHARTS = [
25 | {
26 | reportType: "ga",
27 | query: {
28 | dimensions: "ga:date",
29 | metrics: "ga:sessions",
30 | "start-date": "10daysAgo",
31 | "end-date": "yesterday"
32 | },
33 | chart: {
34 | type: "LINE",
35 | options: {
36 | title: "Last 10 days sessions",
37 | width: '100%'
38 | }
39 | }
40 | },
41 | {
42 | reportType: "ga",
43 | query: {
44 | dimensions: "ga:date",
45 | metrics: "ga:sessions",
46 | "start-date": "30daysAgo",
47 | "end-date": "yesterday"
48 | },
49 | chart: {
50 | type: "LINE",
51 | options: {
52 | title: "Last 30 days sessions",
53 | width: '100%'
54 | }
55 | }
56 | },
57 | {
58 | reportType: "ga",
59 | query: {
60 | dimensions: "ga:date",
61 | metrics: "ga:pageviews",
62 | "start-date": "30daysAgo",
63 | "end-date": "yesterday"
64 | },
65 | chart: {
66 | type: "LINE",
67 | options: {
68 | title: "Last 30 days pageviews",
69 | width: '100%'
70 | }
71 | }
72 | },
73 | {
74 | reportType: "ga",
75 | query: {
76 | dimensions: "ga:date",
77 | metrics: "ga:goalCompletionsAll",
78 | "start-date": "30daysAgo",
79 | "end-date": "yesterday"
80 | },
81 | chart: {
82 | type: "LINE",
83 | options: {
84 | title: "Last 30 days conversions",
85 | width: '100%'
86 | }
87 | }
88 | }
89 | ]
90 |
91 | // App credential in the google developer console
92 | var CLIENT_ID = "960315238073-dv345fcj3tkikn506k9lrch73hk9259u.apps.googleusercontent.com"
93 |
94 | class Example extends React.Component {
95 | state = {
96 | ids: "ga:150278027"
97 | }
98 | render() {
99 | const views = {
100 | query: {
101 | ids: this.state.ids
102 | }
103 | }
104 | return (
105 |
106 |
107 |
108 |
109 | Define your view ID :
110 | this.setState({ ids: e.target.value })} value={this.state.ids} />
111 |
112 |
113 |
114 | {CHARTS.map((c, i) => )}
115 |
116 |
117 | )
118 | }
119 | }
120 |
121 | render(, document.getElementById("demo"))
122 |
--------------------------------------------------------------------------------
/nwb.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | type: 'react-component',
3 | npm: {
4 | esModules: true,
5 | umd: false
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-analytics-widget",
3 | "version": "1.2.0",
4 | "description": "Embed Google Analytics widgets in your React applications",
5 | "main": "lib/index.js",
6 | "module": "es/index.js",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/revolunet/react-analytics-widget.git"
10 | },
11 | "homepage": "https://revolunet.github.io/react-analytics-widget/",
12 | "bugs": {
13 | "url": "https://github.com/revolunet/react-analytics-widget/issues"
14 | },
15 | "files": [
16 | "css",
17 | "es",
18 | "lib",
19 | "umd"
20 | ],
21 | "scripts": {
22 | "build": "nwb build-react-component",
23 | "clean": "nwb clean-module && nwb clean-demo",
24 | "start": "nwb serve-react-demo",
25 | "test": "nwb test-react",
26 | "publish": "gh-pages -d demo/dist && git push",
27 | "test:coverage": "nwb test-react --coverage",
28 | "test:watch": "nwb test-react --server"
29 | },
30 | "peerDependencies": {
31 | "react": "15.x"
32 | },
33 | "devDependencies": {
34 | "gh-pages": "^1.0.0",
35 | "nwb": "0.18.x",
36 | "react": "^15.6.1",
37 | "react-dom": "^15.6.1",
38 | "react-github-corner": "^0.3.0"
39 | },
40 | "author": "Julien Bouquillon ",
41 | "license": "MIT",
42 | "keywords": [
43 | "react-component",
44 | "analytics",
45 | "widget"
46 | ]
47 | }
48 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render } from "react-dom";
3 | import PropTypes from 'prop-types';
4 |
5 | // dont wait for auth twice, even after unmounts
6 | let isLoaded = false;
7 |
8 | // wait for auth to display children
9 | export class GoogleProvider extends React.Component {
10 | state = {
11 | ready: false
12 | };
13 | componentDidMount() {
14 | this.init();
15 | }
16 | init = () => {
17 | const doAuth = () => {
18 | const authObj = this.props.accessToken ?
19 | {serverAuth: {access_token: this.props.accessToken}} :
20 | {clientid: this.props.clientId};
21 | gapi.analytics.auth &&
22 | gapi.analytics.auth.authorize({
23 | ...authObj,
24 | container: this.authButtonNode
25 | });
26 | };
27 | gapi.analytics.ready(a => {
28 | if (isLoaded) {
29 | this.setState({
30 | ready: true
31 | });
32 | return;
33 | }
34 | const authResponse = gapi.analytics.auth.getAuthResponse();
35 | if (!authResponse) {
36 | gapi.analytics.auth.on("success", response => {
37 | this.setState({
38 | ready: true
39 | });
40 | });
41 | } else {
42 | this.setState({
43 | ready: true
44 | });
45 | }
46 | doAuth();
47 | });
48 | };
49 | render() {
50 | return (
51 |
52 | {this.props.clientId &&
(this.authButtonNode = node)} />}
53 | {this.state.ready && this.props.children}
54 |
55 | );
56 | }
57 | }
58 | GoogleProvider.propTypes = {
59 | clientId: PropTypes.string,
60 | accessToken: PropTypes.string,
61 | }
62 |
63 | // single chart
64 | export class GoogleDataChart extends React.Component {
65 | componentDidMount() {
66 | this.loadChart();
67 | }
68 | componentWillUpdate() {
69 | this.loadChart();
70 | }
71 | componentWillUnmount() {
72 | // TODO: cleanup
73 | }
74 | loadChart = () => {
75 | const config = {
76 | ...this.props.config,
77 | chart: {
78 | ...this.props.config.chart,
79 | container: this.chartNode
80 | }
81 | };
82 | this.chart = new gapi.analytics.googleCharts.DataChart(config);
83 | this.chart.set(this.props.views).execute();
84 | };
85 | render() {
86 | return (
87 |
(this.chartNode = node)}
91 | />
92 | );
93 | }
94 | }
95 |
--------------------------------------------------------------------------------