Skip to content

Commit 8c84cd0

Browse files
address KS's final change requests
2 parents d2328cf + 9f5ce5f commit 8c84cd0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+3279
-926
lines changed

.gitignore

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88
# testing
99
/coverage
1010

11-
# production
12-
/build
13-
/dist
14-
1511
# Webstorm IDE
1612
/.idea
1713

Gruntfile.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,24 @@ module.exports = function(grunt) {
2020

2121
grunt.initConfig({
2222
'pkg': grunt.file.readJSON('package.json'),
23+
2324
'closure-compiler': {
2425
options: {
26+
// All files must be listed explicitly in the right order or
27+
// strange errors will occur in the demo site.
2528
js: [
2629
'node_modules/google-closure-library/closure/goog/base.js',
27-
'data-layer-helper/src/**.js',
28-
'src/**.js',
29-
'!src/main.js',
30+
'data-layer-helper/src/logging.js',
31+
'data-layer-helper/src/plain/plain.js',
32+
'data-layer-helper/src/helper/utils.js',
33+
'data-layer-helper/src/helper/data-layer-helper.js',
34+
'src/logging.js',
35+
'src/storage/**.js',
36+
'src/eventProcessor/EventProcessorInterface.js',
37+
'src/eventProcessor/generateUniqueId.js',
38+
'src/eventProcessor/GoogleAnalyticsEventProcessor.js',
39+
'src/config/configProcessors.js',
40+
'src/config/setup.js',
3041
'!src/eventProcessor/EventProcessorInterface.js',
3142
'!src/storage/StorageInterface.js',
3243
],
@@ -41,6 +52,7 @@ module.exports = function(grunt) {
4152
language_out: 'ECMASCRIPT5_STRICT',
4253
output_wrapper: '(function(){%output%})();',
4354
jscomp_warning: 'lintChecks',
55+
generate_exports: true,
4456
},
4557
distribution: {
4658
files: {
@@ -55,10 +67,21 @@ module.exports = function(grunt) {
5567
'dist/measure-debug.js': 'src/main.js',
5668
},
5769
options: {
58-
define: 'ML_DEBUG=true',
70+
define: 'ML_DEBUG=true, DLH_DEBUG=true',
5971
create_source_map: 'dist/measure-debug.js.map',
6072
},
6173
},
74+
site: {
75+
files: {
76+
'demo/public/measure-no-config.js': 'src/mainNoConfig.js',
77+
},
78+
options: {
79+
// If we set ML_DEBUG to true, then the site will not send
80+
// events to google analytics, instead sending a debug
81+
// request and posting results in the console.
82+
define: 'DLH_DEBUG=true',
83+
},
84+
},
6285
},
6386
'karma': {
6487
options: {

README.md

Lines changed: 17 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,14 @@ Measurement library will provide an open source alternative for sites/apps to se
1515
- [Usage](#usage)
1616
- [Event Command](#event-command)
1717
- [Set Command](#set-command)
18-
- [Event Processors](#event-processors)
19-
- [Google Analytics](#google-analytics)
20-
- [Custom Event Processor](#custom-event-processor)
21-
- [Storage Interfaces](#storage-interfaces)
22-
- [Cookies](#cookies)
23-
- [Custom Storage Interface](#custom-storage-interface)
24-
- [Local Setup](#local-setup)
25-
- [Creating the build](#creating-the-build)
26-
- [Running Tests Interactively](#running-tests-interactively)
2718

2819
# Overview
2920
Measurement Library is a utility to help developers send data collected from their website to
3021
other libraries for analytics. After specifying settings in a script tag, you can process any
3122
sent events using a variety of built in event processors (e.g. sending data to Google Analytics).
3223

3324
Data from events or generated by event processors is automatically saved to persist between visits using your choice of
34-
a variety of different storage options (e.g. cookies).
25+
a variety of different storage options (e.g. cookies). [Read the docs](https://googleinterns.github.io/measurement-library/#) to learn more.
3526

3627
# Installation
3728
First, install the package with your favorite package manager:
@@ -41,152 +32,46 @@ yarn add measurement-library
4132
npm install measurement-library
4233
```
4334

44-
Next, choose [the event processor](#event-processors) and [the storage implementation](#storage-interfaces)
35+
Next, choose [the event processor](https://googleinterns.github.io/measurement-library/#EventProcessors) and
36+
[the storage implementation]((https://googleinterns.github.io/measurement-library/#StorageInterfaces))
4537
to use and include this code in your `<head>` tag. It should be placed as high up in the block as possible
4638
in order to catch users who leave immediately after loading the page, then immediately leave.
4739
```html
4840
<!-- Measurement Library Snippet -->
49-
<script async src="./node_modules/measurement-library/dist/measure"/>
41+
<script async src="/node_modules/measurement-library/dist/measure"/>
5042
<script>
5143
window.dataLayer = window.dataLayer || [];
5244
function measure(){dataLayer.push(arguments);}
53-
// One or more config commands. To send data to google analytics while
45+
// One or more config commands. To send data to google analytics while
5446
// using cookies for storage:
55-
measure('config', 'googleAnalytics', {}, 'cookies', {});
47+
measure('config', 'googleAnalytics', {
48+
'measurement_id': YOUR_MEASUREMENT_ID,
49+
'api_secret': YOUR_API_SECRET,
50+
}, 'cookies', {});
5651
</script>
5752
```
5853

59-
[//]: # (TODO kj: Make the config command use the right settings for google analytics)
60-
6154
As an alternative, you can use the development version when testing your page. The dev version has a bigger file size,
6255
but reports possible errors to the console.
6356
```html
6457
<!-- Measurement Library Snippet (Development Version) -->
65-
<script async src="./node_modules/measurement-library/dist/measure-debug"/>
58+
<script async src="/node_modules/measurement-library/dist/measure-debug"/>
6659
<script>/* Configure script like last example. */ </script>
6760
```
6861

6962
# Usage
70-
After setting up the script tags, you can begin to use the library. All commands
71-
are processed by passing arguments to the `measure()` function.
63+
After setting up the script tag using the `config` command, you can begin to use the library. All commands
64+
are processed by passing arguments to the `measure()` function.
65+
7266

7367
## Event command
7468
When you run the command `measure('event', eventName, eventOptions)`, all registered
75-
[event processors](#event-processors) will read the event and perform actions corresponding
69+
[event processors](https://googleinterns.github.io/measurement-library/#EventProcessors) will read the event and perform actions corresponding
7670
to their API.
7771

7872
## Set command
7973
To save parameters beyond the current page, you can call the command `measure('set', key, value)`.
8074
The registered event processor will determine if the value should be saved, how long the value should
81-
be saved for, and save it. To overwrite this behavior, you can specify a third time-to-live parameter:
82-
`measure('set', key, value, secondsToLive)`. In particular, if `secondsToLive` is 0, no data will be saved
83-
to long term storage.
84-
85-
The set command can also be used to set parameters related to a implementation of
86-
an event processor or storage interface. For example, to modify the default parameters
87-
of the cookies storage, run a `set` command in the script tag before calling
88-
`config`.
89-
90-
```js
91-
// Set the default cookie parameters
92-
measure('set', 'cookies', {prefix: 'my_', expires: 11});
93-
// Use the default cookie parameters: prefix 'my_' and expires 11.
94-
measure('config', 'eventProcessorName', {}, 'cookies', {});
95-
// Override a default cookie parameter: expires is 22 for this storage.
96-
measure('config', 'eventProcessorName', {}, 'cookies', {expires: 22});
97-
```
98-
99-
# Event Processors
100-
## Google Analytics
101-
[//]: # (TODO: kj)
102-
103-
## Custom Event Processor
104-
If none of the built-in processors fit your needs, you can create your own event processor.
105-
An event processor is a class with the 2 methods described in [eventProcessorInterface.js](/src/eventProcessor/EventProcessorInterface.js)
106-
in addition to a constructor that takes an options object as it's only parameter.
107-
108-
```html
109-
<script async src="./node_modules/measurement-library/dist/measure"/>
110-
<script>
111-
window.dataLayer = window.dataLayer || [];
112-
function measure(){dataLayer.push(arguments);}
113-
class MyProcessor {
114-
constructor({theNumber});
115-
processEvent(storageInterface, modelInterface, eventName, eventOptions);
116-
persistTime(key, value);
117-
}
118-
// Call the class constructor
119-
measure(config, myProcessor, {theNumber: 42}, 'cookies', {});
120-
// Calls the processEvent function with parameters
121-
// (cookies storage, short term storage, 'jump', {height: 6}).
122-
measure('event', 'jump', {height: 6})
123-
// Sets a value in the storage with secondsToLive determined by
124-
// the persistTime function of the event processor.
125-
measure('set', 'key', 'value');
126-
</script>
127-
```
128-
129-
# Storage Interfaces
130-
## Cookies
131-
[//]: # (TODO: pedro)
132-
133-
## Custom Storage Interface
134-
If none of the built-in storage systems fit your needs, you can create your own storage interface.
135-
A storage interface is a class with the 2 methods described in [storageInterface.js](/src/storage/StorageInterface.js)
136-
in addition to a constructor that takes an options object as it's only parameter.
137-
138-
```html
139-
<script async src="./node_modules/measurement-library/dist/measure"/>
140-
<script>
141-
window.dataLayer = window.dataLayer || [];
142-
function measure(){dataLayer.push(arguments);}
143-
class MyStorage {
144-
constructor({theNumber});
145-
save(key, value, secondsToLive= 3600*24) {};
146-
load(key, defaultValue= undefined) {};
147-
}
148-
// Call the class constructor.
149-
measure(config, 'eventProcessorName', {}, MyStorage, {theNumber: 42});
150-
// Call the save command with secondsToLive determined by the persistTime
151-
// function of the event processor.
152-
measure('set', 'key', 'value');
153-
</script>
154-
```
155-
156-
# Local Setup
157-
## Creating The Build
158-
You will need to have either [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
159-
or [yarn](https://classic.yarnpkg.com/en/docs/install/#debian-stable) installed.
160-
161-
First, install dependencies with yarn or npm
162-
```shell script
163-
yarn install
164-
# or
165-
npm install
166-
```
167-
168-
Next, run the tests using yarn or npm:
169-
170-
```shell script
171-
yarn test
172-
# or
173-
npm run test
174-
```
175-
176-
## Running Tests Interactively
177-
You can also run the tests "interactively" via Karma directly.
178-
179-
```shell script
180-
yarn unit
181-
# or
182-
npm run unit
183-
```
184-
185-
To run the integration tests instead of the unit tests,
186-
187-
```shell script
188-
yarn integration
189-
# or
190-
npm run integration
191-
```
192-
****
75+
be saved for, and save it in the corresponding [storage](https://googleinterns.github.io/measurement-library/#StorageInterfaces).
76+
To overwrite this behavior, you can specify a third time-to-live parameter:
77+
`measure('set', key, value, secondsToLive)`. In particular, if `secondsToLive` is 0, no data will be saved to long term storage.

demo/.env

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
REACT_APP_GA_TRACKING_ID=G-70CMQK5VQE
1+
REACT_APP_GTAG_TRACKING_ID=G-70CMQK5VQE
2+
REACT_APP_MEASURE_TRACKING_ID=G-V6EDGQKHCW
3+
REACT_APP_MEASURE_API_SECRET=hteq-xzISAqOQpb0oNSiEw

demo/package.json

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@testing-library/jest-dom": "^4.2.4",
7-
"@testing-library/react": "^9.5.0",
8-
"@testing-library/user-event": "^7.2.1",
9-
"prismjs": "^1.20.0",
10-
"react": "^16.13.1",
11-
"react-bootstrap": "^1.0.1",
12-
"react-dom": "^16.13.1",
13-
"react-icons": "^3.10.0",
14-
"react-modal-image": "^2.5.0",
15-
"react-redux": "^7.2.0",
16-
"react-router-dom": "^5.2.0",
17-
"react-scripts": "3.4.1",
18-
"redux": "^4.0.5",
19-
"uuid": "^8.1.0"
6+
"@testing-library/jest-dom": "~4.2.4",
7+
"@testing-library/react": "~9.5.0",
8+
"@testing-library/user-event": "~7.2.1",
9+
"prismjs": "~1.21.0",
10+
"react": "~16.13.1",
11+
"react-bootstrap": "~1.3.0",
12+
"react-dom": "~16.13.1",
13+
"react-icons": "~3.10.0",
14+
"react-modal-image": "~2.5.0",
15+
"react-redux": "~7.2.0",
16+
"react-router-dom": "~5.2.0",
17+
"react-scripts": "~3.4.3",
18+
"redux": "~4.0.5",
19+
"uuid": "~8.3.0"
2020
},
2121
"scripts": {
2222
"start": "serve -s build",
@@ -42,9 +42,7 @@
4242
]
4343
},
4444
"devDependencies": {
45-
"eslint": "^6.6.0",
46-
"eslint-config-google": "^0.14.0",
47-
"eslint-plugin-react": "^7.20.0",
48-
"prop-types": "^15.7.2"
45+
"eslint-plugin-react": "~7.20.0",
46+
"prop-types": "~15.7.2"
4947
}
5048
}

demo/public/index.html

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
<!DOCTYPE html>
22
<html lang="en">
33
<head>
4-
<script async src="https://www.googletagmanager.com/gtag/js?id=%REACT_APP_GA_TRACKING_ID%"></script>
4+
<!-- Include gtag on the default data layer -->
5+
<script async src="https://www.googletagmanager.com/gtag/js?id=%REACT_APP_GTAG_TRACKING_ID%"></script>
56
<script>
6-
window.dataLayer = window.dataLayer || [];
7-
function gtag(){dataLayer.push(arguments);}
8-
gtag('js', new Date());
7+
window.dataLayer = window.dataLayer || [];
8+
function gtag(){dataLayer.push(arguments);}
9+
gtag('js', new Date());
10+
</script>
11+
<!-- Include measurement library. We could run this on the default data
12+
layer, but it would send duplicate events with gtag. Though the
13+
two libraries are fairly compatible, to be safe, this snippet
14+
constructs measurement library using a different dataLayer.
15+
To do this, we do not load the library asynchronously and include
16+
a measure-setup compiled file that does not run commands on load,
17+
then call it in the setup script. -->
18+
<script src="/measure-no-config.js"></script>
19+
<script>
20+
measureDataLayer = [];
21+
window.setupMeasure(measureDataLayer);
22+
function measure(){measureDataLayer.push(arguments);}
23+
measure("config", "googleAnalytics", {
24+
"measurement_id": "%REACT_APP_MEASURE_TRACKING_ID%",
25+
"api_secret": "%REACT_APP_MEASURE_API_SECRET%"
26+
}, "cookies", {});
927
</script>
1028
<meta charset="utf-8" />
1129
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />

demo/public/measure-no-config.js

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)