├── .babelrc
├── .eslintrc.js
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .npmignore
├── .nvmrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── dev
├── .gitignore
├── gatsby-config.js
├── nodemon.json
├── package.json
├── src
│ └── pages
│ │ └── index.js
├── static
│ └── favicon.ico
└── test
│ ├── mocha-config.js
│ ├── mocha-environment.js
│ └── mocha-setup.js
├── example
├── .gitignore
├── LICENSE
├── README.md
├── assets
│ ├── segment_ui.png
│ ├── track_event.png
│ └── track_page.png
├── gatsby-config.js
├── package.json
└── src
│ ├── components
│ ├── header.js
│ ├── image.js
│ ├── layout.css
│ ├── layout.js
│ └── seo.js
│ ├── images
│ └── gatsby-icon.png
│ └── pages
│ ├── 404.js
│ ├── index.js
│ └── page-2.js
├── index.js
├── package.json
├── src
├── gatsby-browser.js
└── gatsby-ssr.js
└── tests
├── .eslintrc.js
├── gatsby-2
├── gatsby-config.js
├── package.json
├── src
│ └── pages
│ │ └── index.js
├── static
│ └── favicon.ico
└── test
│ ├── mocha-config.js
│ ├── mocha-environment.js
│ └── mocha-setup.js
├── gatsby-3
├── gatsby-config.js
├── package.json
├── src
│ └── pages
│ │ └── index.js
├── static
│ └── favicon.ico
└── test
│ ├── mocha-config.js
│ ├── mocha-environment.js
│ └── mocha-setup.js
├── gatsby-4
├── gatsby-config.js
├── package.json
├── src
│ └── pages
│ │ └── index.js
├── static
│ └── favicon.ico
└── test
│ ├── mocha-config.js
│ ├── mocha-environment.js
│ └── mocha-setup.js
├── gatsby-5
├── gatsby-config.js
├── package.json
├── src
│ └── pages
│ │ └── index.js
├── static
│ └── favicon.ico
└── test
│ ├── mocha-config.js
│ ├── mocha-environment.js
│ └── mocha-setup.js
└── shared
└── tests.test.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env", "react"],
3 | "comments": false
4 | }
5 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "env": {
3 | "browser": true,
4 | "es2021": true,
5 | "node": true,
6 | },
7 | "extends": [
8 | "eslint:recommended",
9 | "plugin:react/recommended"
10 | ],
11 | "parserOptions": {
12 | "ecmaFeatures": {
13 | "jsx": true
14 | },
15 | "ecmaVersion": 12,
16 | "sourceType": "module"
17 | },
18 | "plugins": [
19 | "react"
20 | ],
21 | "rules": {
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: CI Tests
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 | strategy:
13 | #fail-fast: false
14 | matrix:
15 | # gatsby 5 can only run on node 18.x and will be added below via "include"
16 | gatsby-version: [2, 3, 4]
17 | node-version: [12.x, 14.x, 16.x, 18.x]
18 | exclude:
19 | # excludes gatsby 4 on node 12.x because it's not compatible
20 | - node-version: 12.x
21 | gatsby-version: 4
22 | # excludes gatsby 2 on node 18.x because it's not compatible
23 | - node-version: 18.x
24 | gatsby-version: 2
25 | include:
26 | # gatsby 5 can only run on node 18.x
27 | - node-version: 18.x
28 | gatsby-version: 5
29 |
30 |
31 | steps:
32 | - uses: actions/checkout@v2
33 |
34 | # TODO: Figure out a way to cache the node_modules using `actions/setup-node` while also
35 | # installing the *latest* version of each major version of Gatsby
36 | - name: Use Node.js ${{ matrix.node-version }}
37 | uses: actions/setup-node@v3
38 | with:
39 | node-version: ${{ matrix.node-version }}
40 |
41 | # Run the yarn install on the parent directory so that build deps are present
42 | - run: yarn install
43 |
44 | # Run yarn test in the specific gatsby version directory
45 | - run: yarn test
46 | working-directory: ./tests/gatsby-${{ matrix.gatsby-version }}
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # possible output files from local builds
2 | gatsby-browser.js
3 | gatsby-node.js
4 | gatsby-ssr.js
5 |
6 | # gatsby files
7 | .cache/
8 | public
9 |
10 | node_modules
11 |
12 | # Them lockfiles
13 | yarn.lock
14 | package-lock.json
15 |
16 | # Output of 'npm pack'
17 | *.tgz
18 |
19 | *.DS_Store
20 |
21 | yarn-error.log
22 |
23 | # Finally, whitelist all .js files in the src/ directory
24 | !src/*.js
25 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # Ignore everything by default
2 | *
3 |
4 | # Whitelist these
5 | !/index.js
6 | !/gatsby-browser.js
7 | !/gatsby-ssr.js
8 | !/README.md
9 | !/CHANGELOG.md
10 | !/LICENSE
11 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | v18
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 5.0.0
2 | - BREAKING CHANGE: The `options` now support more complex things, and some thing are renamed. Please check out all of the options in the `README`.
3 |
4 | ## 4.0.3
5 | - Ensure that cb is a function before calling it. https://github.com/benjaminhoffman/gatsby-plugin-segment-js/pull/57
6 |
7 | ## 4.0.2
8 | - Fix syntax error in delayed loader code. https://github.com/benjaminhoffman/gatsby-plugin-segment-js/pull/56
9 |
10 | ## 4.0.1
11 | - Better idempotency. https://github.com/benjaminhoffman/gatsby-plugin-segment-js/pull/54
12 |
13 | ## 4.0.0
14 |
15 | - Add `includeTitleInPageCall` option, and set it to `true` by default. Strictly speaking, this was a "breaking change", hence the new major version.
16 | - Fix bug where `analytics.page()` would be called twice.
17 |
18 | ## 3.7.2
19 |
20 | - Updated `gatsby` peer dependency to support `^2 || ^3 || ^4 || ^5` https://github.com/benjaminhoffman/gatsby-plugin-segment-js/pull/52
21 |
22 | ## 3.7.1
23 |
24 | - Updated `gatsby` peer dependency to support `^2 || ^3 || ^4` https://github.com/benjaminhoffman/gatsby-plugin-segment-js/pull/43
25 |
26 | ## 3.7.0
27 |
28 | - Updated default snippet to `4.13.2`
29 | - Added `customSnippet` option to allow for providing arbitrary snippet code
30 | - Decreased NPM package size
31 | - Some small optimizations
32 | - Added linting for developers
33 |
34 | - Added correct peer dependencies(thanks @LekoArts) and updated readme to show correct usage of analytics.load(thanks @seankovacs)
35 |
36 | ## 3.6.1
37 |
38 | - Added correct peer dependencies(thanks @LekoArts) and updated readme to show correct usage of analytics.load(thanks @seankovacs)
39 |
40 | ## 3.6.0
41 |
42 | - Added `trackPageDelay` option that allows specifying the amount of time to wait before calling `trackPage`. Thanks to @sreucherand!
43 |
44 | ## 3.5.0
45 |
46 | - Added `addSourceMiddleware`, `addIntegrationMiddleware`, `setAnonymousId`, and `addDestinationMiddleware` methods to Segment snippet
47 |
48 | ## 3.4.0
49 |
50 | - Adds `manualLoad` plugin option to allow users to manually load Segment snippet, e.g. waiting for a user to opt into being tracked for GDPR
51 |
52 | ## 3.3.1
53 |
54 | - Send `document.title` with page tracking events for enhanced event data
55 |
56 | ## 3.3.0
57 |
58 | - Adds a 50ms delay to page tracking calls to prevent erroneously sending duplicate page events
59 |
60 | ## 3.2.1
61 |
62 | - Delete package-lock.json
63 |
64 | ## 3.2.0
65 |
66 | - Bug: Built files not uploaded to npm
67 |
68 | ## 3.1.1
69 |
70 | - Updated README.md
71 |
72 | ## 3.1.0
73 |
74 | - NEW FEATURE: we've added one new feature with two options: `delayLoad` and its friend `delayLoadTime`. When the former is set to true, we will delay loading Segment `delayLoadTime` seconds _after_ either a route change or user page scroll, whichever comes first. This functionality was built to help with SEO, UX, etc by preventing Segment from increasing your TTI.
75 |
76 | ## 3.0.0
77 |
78 | - BREAKING CHANGE: you must now explicitly pass `trackPage: true` in your `gatsby-config.js` file if you want us to automatically track pageviews
79 |
80 | - BREAKING CHANGE: previously we would only fire `analytics.page()` on the initial page load. But now we will invoke it on each route transition. See README for more details.
81 |
82 | - Added example dir
83 |
84 | - Expanded README.md and adds CHANGELOG.md
85 |
86 | ## 2.1.2
87 |
88 | - Bumps Segment snippet from 4.0.0 to 4.1.0
89 |
90 | ## 2.0.0
91 |
92 | - Basic version working
93 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Benjamin Hoffman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gatsby-plugin-segment-js
2 |
3 | A lightweight & feature-rich Gatsby plugin to easily add [Segment JS snippet](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/quickstart/) to your site.
4 |
5 | ## We need your help! 🙏🏽
6 | We're looking for active contributors to this repo! If you're interested, simply open an issue or PR of your own and indicate that you'd like to help. Check out our open issues and PRs. We also need to beef up testing. Contributors get to:
7 | - manage versioning and deploys by publishing new versions to NPM
8 | - determine which features get launched by merging pull requests
9 | - oversee the community through commenting on and managing pull requests and issues
10 |
11 | ⚜️ Being an active contributor is great for the community and your engineering resume.⚜️
12 |
13 | ## Features
14 |
15 | Packed with features:
16 |
17 | - use multiple write keys (one for prod env, another optional one for dev)
18 | - disable page view tracking (just in case you want to add it later manually)
19 | - will use a default Segment code snippet (currently `v4.15.3`), or you can provide your own custom snippet
20 |
21 | ## Install
22 |
23 | - NPM: `$ npm install --save gatsby-plugin-segment-js`
24 | - YARN: `$ yarn add gatsby-plugin-segment-js`
25 |
26 | ## How to use
27 |
28 | ### Setup
29 |
30 | In your gatsby-config.js file:
31 |
32 | ```javascript
33 | plugins: [
34 | {
35 | resolve: `gatsby-plugin-segment-js`,
36 | options: {
37 | // your segment write key for your production environment
38 | // when process.env.NODE_ENV === 'production'
39 | // required; non-empty string
40 | prodKey: 'SEGMENT_PRODUCTION_WRITE_KEY',
41 |
42 | // if you have a development env for your segment account, paste that key here
43 | // when process.env.NODE_ENV === 'development'
44 | // optional; non-empty string
45 | devKey: 'SEGMENT_DEV_WRITE_KEY',
46 |
47 | // Boolean indicating if you want this plugin to perform any automated analytics.page() calls
48 | // at all, or not.
49 | // If set to false, see below on how to track pageviews manually.
50 | //
51 | // This plugin will attempt to intelligently prevent duplicate page() calls.
52 | //
53 | // Default: true
54 | trackPage: true,
55 |
56 | // Boolean indicating if you want this plugin to perform a page() call immediately once the snippet
57 | // is loaded.
58 | //
59 | // You might want to disable this if you *only* want page() calls to occur upon Client-side routing
60 | // updates. See `trackPageOnRouteUpdate` option.
61 | //
62 | // This plugin will still attempt to intelligently prevent duplicate page() calls.
63 | //
64 | // Default: true
65 | trackPageImmediately: true,
66 |
67 | // Boolean indicating whether to ignore `page` calls by this plugin before we call `analytics.load`
68 | // and/or the `ready` event has been emitted by `analytics`.
69 | //
70 | // Useful in some cases to prevent issues "queuing" `page` events before Segment is fully loaded.
71 | trackPageOnlyIfReady: false,
72 |
73 | // Boolean indicating whether to perform any page() calls during Client-side routing updates.
74 | //
75 | // You might want to disable `trackPageImmediately` if you *only* want page() calls to occur upon
76 | // Client-side routing updates.
77 | //
78 | // This plugin will still attempt to intelligently prevent duplicate page() calls.
79 | //
80 | // Default: true
81 | trackPageOnRouteUpdate: true,
82 |
83 | // Number indicating what delay (in ms) should be used when calling analytics.page() in response
84 | // to a Gatsby `onRouteUpdate` event. This can help to ensure that the segment route tracking is
85 | // in sync with the actual Gatsby route. Otherwise you can end up in a state where the Segment
86 | // page tracking reports the previous page on route change.
87 | //
88 | // See https://www.gatsbyjs.com/docs/reference/config-files/gatsby-browser/ for more information.
89 | //
90 | // Default: 50
91 | trackPageOnRouteUpdateDelay: 50,
92 |
93 | // Boolean indicating whether or not to add the document.title as the first argument to
94 | // the analytics.page() calls. Segment uses some sane defaults, but some users of this plugin
95 | // have wanted to do this in the past.
96 | //
97 | // E.g `analytics.page(document.title)`
98 | //
99 | // Default: false
100 | trackPageWithTitle: false,
101 |
102 | // Boolean indicating whether to call analytics.load() immediately, or to delay it by a specified
103 | // number of ms. Can be useful if you want to wait a specifc amount of time before calling
104 | // analytics.load() and kicking off the activity that occurs with that call.
105 | //
106 | // Default: false
107 | delayLoad: false,
108 |
109 | // Number indicating (in ms) how long to wait for before analytics.load() will be called if
110 | // the `delayLoad` option is set to `true`.
111 | //
112 | // Default: 1000
113 | delayLoadDelay: 1000,
114 |
115 | // Boolean indicating whether to delay calling analytics.load() until either:
116 | // 1) The User interacts with the page by scrolling
117 | // OR
118 | // 2) The User triggers a Gatsby route change.
119 | //
120 | // The `delayLoad` option can be used in addition to this option.
121 | //
122 | // NOTE:
123 | // The route change will only be triggered if you leverage client-side routing (ie, Gatsby )
124 | // So if you leverage server-side routing with this feature, only a User scroll will trigger
125 | // the `load` call. This is because client-side routing does not do
126 | // a full page refresh, but server-side routing does. Therfore server-side routing will never
127 | // appear to have been triggered by a User interaction.
128 | //
129 | // This is an advanced feature most often used to try to help improve your website's TTI (for SEO, UX, etc).
130 | //
131 | // See here for more context:
132 | // Client-side routing and browser code: https://www.gatsbyjs.com/docs/reference/config-files/gatsby-browser/
133 | // GIF: https://github.com/benjaminhoffman/gatsby-plugin-segment-js/pull/19#issuecomment-559569483
134 | // TTI: https://github.com/GoogleChrome/lighthouse/blob/master/docs/scoring.md#performance
135 | // Problem/solution: https://marketingexamples.com/seo/performance
136 | //
137 | // Default: false
138 | delayLoadUntilActivity: false,
139 |
140 | // Number indicating (in ms) any additional delay to wait before calling analytics.load()
141 | // after User "activity" has occurred in conjunction with the `delayLoadUntilActivity` option.
142 | //
143 | // Default: 0
144 | delayLoadUntilActivityAdditionalDelay: 0,
145 |
146 | // Whether to completely skip calling `analytics.load({writeKey})`.
147 | // ADVANCED FEATURE: only use if you are calling `analytics.load({writeKey})` manually
148 | // elsewhere in your code or are using a library
149 | // like: https://github.com/segmentio/consent-manager that will call it for you.
150 | // Useful for only loading the tracking script once a user has opted in to being tracked, for example.
151 | //
152 | // Default: false
153 | manualLoad: false,
154 |
155 | // If you need to proxy events through a custom endpoint,
156 | // add a `host` property (defaults to https://cdn.segment.io)
157 | // Segment docs:
158 | // - https://segment.com/docs/connections/sources/custom-domains
159 | // - https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/#proxy
160 | //
161 | // Default: 'https://cdn.segment.io'
162 | host: 'https://override-segment-endpoint',
163 |
164 | // This package will use a default version of Segment's code snippet, but
165 | // if you'd like to include your own you can do so here. This is useful if
166 | // the version this package uses is different than the one you'd like to
167 | // use...or you need to do something custom.
168 | // While you should NOT use a back-ticked template string here, the string
169 | // will be evaluated as template literal with the following variables
170 | // available to it:
171 | // - `writeKey`: The appropriate value from the `prodKey` and `devKey`
172 | // options, based on the `NODE_ENV`
173 | // - any of the other options passed here
174 | //
175 | // NOTES:
176 | // - If you provide a custom snippet, an immediate call to
177 | // `analytics.load()` and/or `analytics.page()` will not be added by
178 | // this plugin. You can - of course - add them yourself to your snippet.
179 | // - If your custom snippet does not include a call to `analytics.load()`
180 | // then you must either:
181 | // 1. Manually load it and set the `manualLoad` option here to `true`
182 | // 2. Use the `delayLoad` option here
183 | customSnippet: '!function(){var analytics=window.analytics||[];...;analytics.load("${writeKey}");analytics.page();}}();'
184 | }
185 | }
186 | ];
187 | ```
188 |
189 | ### Loading
190 |
191 | A typical Segment setup using this plugin will add an initial "snippet" for Segment to the page. Once that snippet is there, it needs to be "loaded" completely by making a call to `analytics.load()` before it will actually send over any events to Segment. This `load` call causes a flurry of XHR calls, and some people seem to be quite concerned with having those calls not occur until after some delay - usually for SEO scores, though it's not clear to me if the way Segment handles `load` calls will impact TTI, etc. Regardless, if you want this plugin to delay calling `load`, you have 2 options:
192 | 1. `delayLoad`: This will cause a straightforward delay before `load` is called. Use in conjunction with `delayLoadDelay` to tweak the amount of the delay.
193 | 2. `delayLoadUntilActivity`: This will wait to call `load` until __either__ (a) the user triggers a "scroll" event or (b) the user triggers route change. This option will take precendence over the `delayLoad` option.
194 |
195 | ### Track Events
196 |
197 | If you want to track events, you simply invoke Segment as normal in your React components — (`window.analytics.track('Event Name', {...})` — and you should see the events within your Segment debugger! For example, if you wanted to track events on a click, it may look something like this:
198 |
199 | ```javascript
200 | class IndexPage extends React.Component {
201 | ...
202 | _handleClick() {
203 | window.analytics.track("Track Event Fired", {
204 | userId: user.id,
205 | gender: 'male',
206 | age: 33,
207 | });
208 | }
209 | render() {
210 | return (
211 |
212 |
213 | Click here
214 | {" "}
215 | to see a track event
216 |
217 | );
218 | }
219 | }
220 | ```
221 |
222 | ### Track Pageviews
223 |
224 | If you want to track pageviews automatically, set (or leave) `trackPage` to `true` in your `gatsby-config.js` file. What we mean by _"automatically"_ is that we will intelligently decide how or when to invoke `window.analytics.page()` for you.
225 |
226 | This involves identifying if the last `page` call was made while the User was on the same `location.pathname` as the previous `page` call. If they appear to be the same, we will skip the duplicate call.
227 |
228 | This plugin can also leverage Gatsby's `onRouteUpdate` API in the `gatsby-browser.js` file ([link][on-route-update]) if you so desire. This is accomplished by setting (or leaving) the `trackPageOnRouteUpdate` to `true`. If this option is enabled, we will make a `page` call every time that the `onRouteUpdate` handler is called. That includes the initial route, and any route changes.
229 |
230 | If you only want to use this plugin to inject and load Segment, and not make any `page` calls, this can be done. Just set `trackPage: false`. But then you will have to make `page` calls yourself in your `gatsby-browser.js` file, like this:
231 |
232 | ```javascript
233 | // gatsby-browser.js
234 | exports.onRouteUpdate = () => {
235 | window.analytics && window.analytics.page();
236 | };
237 | ```
238 |
239 | [on-route-update]: https://www.gatsbyjs.org/docs/browser-apis/#onRouteUpdate
--------------------------------------------------------------------------------
/dev/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 |
--------------------------------------------------------------------------------
/dev/gatsby-config.js:
--------------------------------------------------------------------------------
1 | // For future developers: create a .env file in this directory an populate it
2 | // with the ENV keys below to use them and not risk checking in your keys to
3 | // version control
4 | require('dotenv').config()
5 |
6 | /**
7 | * Configure your Gatsby site with this file.
8 | *
9 | * See: https://www.gatsbyjs.com/docs/gatsby-config/
10 | */
11 |
12 | module.exports = {
13 | /* Your site config here */
14 | plugins: [
15 | {
16 | resolve: require.resolve('..'),
17 | options: {
18 | prodKey: process.env.SEGMENT_KEY_PROD || 'SEGMENT_PROD_KEY',
19 | devKey: process.env.SEGMENT_KEY_DEV || 'SEGMENT_DEV_KEY',
20 |
21 | trackPage: true,
22 | trackPageImmediately: true,
23 | trackPageOnlyIfReady: true,
24 | trackPageOnRouteUpdate: true,
25 | trackPageOnRouteUpdateDelay: 5000,
26 |
27 | delayLoad: true,
28 | delayLoadDelay: 5000,
29 |
30 | delayLoadUntilActivity: true,
31 | delayLoadUntilActivityAdditionalDelay: 1000,
32 | }
33 | },
34 | ],
35 | }
36 |
--------------------------------------------------------------------------------
/dev/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "verbose": true,
3 | "ext": "js,json",
4 | "watch": [
5 | "./gatsby-config.js",
6 | "../gatsby-browser.js",
7 | "../gatsby-ssr.js"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/dev/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-plugin-segment-js-test-gatsby-5",
3 | "private": true,
4 | "description": "A simple Gatsby app to test the plugin with Gatsby 5",
5 | "version": "0.1.0",
6 | "license": "0BSD",
7 | "scripts": {
8 | "build": "gatsby build",
9 | "clean": "gatsby clean",
10 | "develop": "nodemon --config ./nodemon.json -x 'gatsby develop'",
11 | "developp": "gatsby develop",
12 | "plugin:build": "yarn --cwd .. build",
13 | "plugin:build:watch": "yarn --cwd .. build:watch",
14 | "test": "mocha --config ./test/mocha-config.js",
15 | "test:prepare": "yarn plugin:build && yarn clean && yarn build",
16 | "test:all": "yarn test:prepare && yarn test"
17 | },
18 | "devDependencies": {
19 | "chai": "^4.3.4",
20 | "dotenv": "^16.0.3",
21 | "gatsby": "^5",
22 | "mocha": "^9.1.3",
23 | "nodemon": "^2.0.20",
24 | "react": "^18.0.0",
25 | "react-dom": "^18.0.0"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/dev/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | export default function Home() {
4 | return
Hello world!
5 | }
6 |
--------------------------------------------------------------------------------
/dev/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjaminhoffman/gatsby-plugin-segment-js/efa49a609b0f08e0997180ed87e3fd727e6521e8/dev/static/favicon.ico
--------------------------------------------------------------------------------
/dev/test/mocha-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | diff: true,
3 | delay: false,
4 | extension: ['js'],
5 | package: './package.json',
6 | reporter: 'spec',
7 | slow: 75,
8 | timeout: 2000,
9 | spec: [
10 | './test/**/*.test.js',
11 | '../tests/shared/**/*.test.js',
12 | ],
13 | require: [
14 | // https://mochajs.org/#-require-module-r-module
15 | // '@babel/register',
16 | './test/mocha-environment.js',
17 | ],
18 | file: './test/mocha-setup.js',
19 | exit: true,
20 | }
21 |
--------------------------------------------------------------------------------
/dev/test/mocha-environment.js:
--------------------------------------------------------------------------------
1 | const chai = require('chai')
2 |
3 | global.chai = chai
4 | global.expect = chai.expect
5 |
--------------------------------------------------------------------------------
/dev/test/mocha-setup.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | // All the tests will be the same, so we'll share them. But we need to tell it where
4 | // to look for things
5 | global.pathToProject = path.resolve(__dirname, '../')
6 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # dotenv environment variables file
55 | .env
56 |
57 | # gatsby files
58 | .cache/
59 | public
60 |
61 | # Mac files
62 | .DS_Store
63 |
64 | # Yarn
65 | yarn-error.log
66 | .pnp/
67 | .pnp.js
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
--------------------------------------------------------------------------------
/example/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 gatsbyjs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Example Usage of `gatsby-plugin-segment`
2 |
3 | To create this example, I used Gatsby's default starter. Then I only modified two files: `src/pages/index.js` and `/gatsby-config.js`. It's a very simple example that doesn't really need to get started but if you still want to get it running, do the following:
4 |
5 | ```bash
6 | $ cd example/
7 | $ yarn
8 | $ yarn develop
9 | ```
10 |
11 | Then open your browser's dev tools. In the _Console_ tab, you should see the message I left for you. And if you click on the _Network_ tab, you'll see the call to Segment.
12 |
13 | Note that if you'd like to send events to your own Segment account, you need to update the API keys in `gatsby-config.js`.
14 |
15 | ## Track Event
16 |
17 |
18 |
19 | ## Track Page
20 |
21 |
22 |
23 | ## Segment UI
24 |
25 |
26 |
--------------------------------------------------------------------------------
/example/assets/segment_ui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjaminhoffman/gatsby-plugin-segment-js/efa49a609b0f08e0997180ed87e3fd727e6521e8/example/assets/segment_ui.png
--------------------------------------------------------------------------------
/example/assets/track_event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjaminhoffman/gatsby-plugin-segment-js/efa49a609b0f08e0997180ed87e3fd727e6521e8/example/assets/track_event.png
--------------------------------------------------------------------------------
/example/assets/track_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benjaminhoffman/gatsby-plugin-segment-js/efa49a609b0f08e0997180ed87e3fd727e6521e8/example/assets/track_page.png
--------------------------------------------------------------------------------
/example/gatsby-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | siteMetadata: {
3 | title: `Gatsby Default Starter`,
4 | description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
5 | author: `@gatsbyjs`
6 | },
7 | plugins: [
8 | {
9 | resolve: `gatsby-plugin-segment-js`,
10 | options: {
11 | prodKey: `ADD_API_KEY_PROD`,
12 | devKey: `ADD_API_KEY_DEV`,
13 | trackPage: true
14 | }
15 | },
16 | `gatsby-plugin-react-helmet`,
17 | {
18 | resolve: `gatsby-source-filesystem`,
19 | options: {
20 | name: `images`,
21 | path: `${__dirname}/src/images`
22 | }
23 | },
24 | `gatsby-transformer-sharp`,
25 | `gatsby-plugin-sharp`,
26 | {
27 | resolve: `gatsby-plugin-manifest`,
28 | options: {
29 | name: `gatsby-starter-default`,
30 | short_name: `starter`,
31 | start_url: `/`,
32 | background_color: `#663399`,
33 | theme_color: `#663399`,
34 | display: `minimal-ui`,
35 | icon: `src/images/gatsby-icon.png` // This path is relative to the root of the site.
36 | }
37 | }
38 | // this (optional) plugin enables Progressive Web App + Offline functionality
39 | // To learn more, visit: https://gatsby.app/offline
40 | // 'gatsby-plugin-offline',
41 | ]
42 | };
43 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-starter-default",
3 | "private": true,
4 | "description": "A simple starter to get up and developing quickly with Gatsby",
5 | "version": "0.1.0",
6 | "author": "Kyle Mathews ",
7 | "dependencies": {
8 | "gatsby": "^2.1.4",
9 | "gatsby-plugin-manifest": "^2.0.17",
10 | "gatsby-plugin-offline": "^2.0.23",
11 | "gatsby-plugin-react-helmet": "^3.0.6",
12 | "gatsby-plugin-segment-js": "latest",
13 | "gatsby-plugin-sharp": "^2.0.20",
14 | "gatsby-source-filesystem": "^2.0.20",
15 | "gatsby-transformer-sharp": "^2.1.13",
16 | "prop-types": "^15.7.2",
17 | "react": "^16.8.2",
18 | "react-dom": "^16.8.2",
19 | "react-helmet": "^5.2.0"
20 | },
21 | "keywords": [
22 | "gatsby"
23 | ],
24 | "license": "MIT",
25 | "scripts": {
26 | "build": "gatsby build",
27 | "develop": "gatsby develop",
28 | "start": "npm run develop",
29 | "serve": "gatsby serve",
30 | "test": "echo \"Write tests! -> https://gatsby.app/unit-testing\""
31 | },
32 | "repository": {
33 | "type": "git",
34 | "url": "https://github.com/gatsbyjs/gatsby-starter-default"
35 | },
36 | "bugs": {
37 | "url": "https://github.com/gatsbyjs/gatsby/issues"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/example/src/components/header.js:
--------------------------------------------------------------------------------
1 | import { Link } from "gatsby"
2 | import PropTypes from "prop-types"
3 | import React from "react"
4 |
5 | const Header = ({ siteTitle }) => (
6 |
12 |
You just hit a route that doesn't exist... the sadness.
11 |
12 | )
13 |
14 | export default NotFoundPage
15 |
--------------------------------------------------------------------------------
/example/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link } from "gatsby";
3 |
4 | import Layout from "../components/layout";
5 | import SEO from "../components/seo";
6 |
7 | class IndexPage extends React.Component {
8 | _handleClick() {
9 | // Invoke `window.analytics.track` and send any
10 | // add'l properties you'd like to send
11 | window.analytics.track("Track Event Fired", {
12 | plugin: "gatsby-plugin-segment",
13 | author: "Ben Hoffman",
14 | href: "https://github.com/benjaminhoffman/gatsby-plugin-segment"
15 | });
16 |
17 | console.log(`
18 | Check your network tab of your dev tools...
19 | you should see the track call there. And if
20 | you put in the correct API keys, you should also
21 | see the track event show up in your Segment account.
22 | `);
23 | }
24 |
25 | render() {
26 | return (
27 |
28 |
29 | {/* Here is where we invoke our Segment track event
30 | via a click handler on Gatsby's component */}
31 |
32 |
33 | Click here
34 | {" "}
35 | to see a track event
36 |
37 | Go to page 2
38 |
39 |
40 | Check full page refresh
41 |
42 |
43 | );
44 | }
45 | }
46 |
47 | export default IndexPage;
48 |
--------------------------------------------------------------------------------
/example/src/pages/page-2.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { Link } from "gatsby"
3 |
4 | import Layout from "../components/layout"
5 | import SEO from "../components/seo"
6 |
7 | const SecondPage = () => (
8 |
9 |
10 |
Hi from the second page
11 |
Welcome to page 2
12 | Go back to the homepage
13 |
14 | )
15 |
16 | export default SecondPage
17 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | // noop
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-plugin-segment-js",
3 | "description": "Easily add Segment JS snippet to your website",
4 | "author": "benjamin hoffman <6520022+benjaminhoffman@users.noreply.github.com>",
5 | "license": "MIT",
6 | "version": "5.0.0",
7 | "main": "gatsby-ssr.js",
8 | "homepage": "https://github.com/benjaminhoffman/gatsby-plugin-segment-js#readme",
9 | "repository": "git@github.com:benjaminhoffman/gatsby-plugin-segment-js.git",
10 | "bugs": {
11 | "url": "https://github.com/benjaminhoffman/gatsby-plugin-segment-js/issues"
12 | },
13 | "keywords": [
14 | "segment",
15 | "segment analytics",
16 | "segment gatsby",
17 | "segment javascript",
18 | "analytics.js",
19 | "gatsby",
20 | "gatsby segment",
21 | "gatsby-plugin",
22 | "gatsby-plugin segment"
23 | ],
24 | "scripts": {
25 | "build": "babel src --out-dir . --ignore tests",
26 | "build:watch": "yarn build -w",
27 | "prepare": "yarn build",
28 | "build-n-pack": "yarn build && yarn pack --filename ./gatsby-plugin-segment-js.tgz"
29 | },
30 | "peerDependencies": {
31 | "gatsby": "^2 || ^3 || ^4 || ^5"
32 | },
33 | "devDependencies": {
34 | "babel-cli": "^6.24.1",
35 | "babel-preset-env": "^1.6.1",
36 | "babel-preset-react": "^6.24.1",
37 | "eslint": "^7.32.0",
38 | "eslint-plugin-mocha": "^9",
39 | "eslint-plugin-react": "^7.24.0"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/gatsby-browser.js:
--------------------------------------------------------------------------------
1 | // https://www.gatsbyjs.com/docs/reference/config-files/gatsby-browser/
2 | exports.onRouteUpdate = ({ prevLocation }, {
3 | // For now this option is SSR only
4 | // delayLoad = false,
5 | // For now this option is SSR only
6 | // delayLoadDelay = 1000,
7 | trackPage = true,
8 | // For now this option is SSR only
9 | // trackOnlyIfLoaded = false,
10 | // For now this option is SSR only
11 | // trackPageOnlyIfReady = false,
12 | // For now, trackPageImmediately should ONLY be a thing that's used in the
13 | // SSR code, while trackPageOnRouteUpdate is more for the Broser code
14 | // trackPageImmediately = true,
15 | trackPageOnRouteUpdate = true,
16 | trackPageOnRouteUpdateDelay = 50,
17 | delayLoadUntilActivity = false,
18 | delayLoadUntilActivityAdditionalDelay = 0,
19 | includeTitleInTrackPage,
20 | trackPageWithTitle = false,
21 | }) => {
22 |
23 | if (typeof includeTitleInTrackPage === 'boolean') {
24 | console.warn('WARNING: option for gatsby-plugin-segment "includeTitleInTrackPage" is deprecated. Please use "trackPageWithTitle" instead.')
25 | trackPageWithTitle = includeTitleInTrackPage
26 | }
27 |
28 | // If this is meant to be responsible for calling "load", then let's do it
29 | // and maybe also track the page once loading is done.
30 | if (prevLocation && delayLoadUntilActivity) {
31 | const additionalLoadDelay = Math.max(0, delayLoadUntilActivityAdditionalDelay || 0)
32 | if (additionalLoadDelay) {
33 | const trackPageCb = () => {
34 | // Just maybe track the page. Since we've already delayed, don't delay more.
35 | return trackPageFn(additionalLoadDelay)
36 | }
37 |
38 | setTimeout(
39 | function () {
40 | const callbackWasQueued = loaderCallback(trackPageCb)
41 | if (!callbackWasQueued) {
42 | trackPageCb()
43 | }
44 | },
45 | additionalLoadDelay,
46 | )
47 | } else {
48 | const callbackWasQueued = loaderCallback(trackPageFn)
49 | if (!callbackWasQueued) {
50 | // Just maybe track the page
51 | trackPageFn()
52 | }
53 | }
54 |
55 | return
56 | }
57 |
58 | // Just maybe track the page
59 | trackPageFn()
60 | return
61 |
62 | function pageviewCallback () {
63 | if (window.gatsbyPluginSegmentPageviewCaller) {
64 | window.gatsbyPluginSegmentPageviewCaller();
65 | } else if (window.analytics) {
66 | window.analytics.page(trackPageWithTitle ? document.title : undefined);
67 | }
68 | }
69 |
70 | // "page" if necessary. delaoyed if necessary
71 | function trackPageFn (alreadyDelayedBy = 0) {
72 | // Do we actually want to track the page?
73 | if (!(trackPage && trackPageOnRouteUpdate)) {
74 | return
75 | }
76 |
77 | // Adding a delay (defaults to 50ms when not provided by plugin option `trackPageDelay`)
78 | // helps to ensure that the segment route tracking is in sync with the actual Gatsby route.
79 | // Otherwise you can end up in a state where the Segment page tracking reports
80 | // the previous page on route change.
81 | const delay = Math.max(0, trackPageOnRouteUpdateDelay || 0) - alreadyDelayedBy
82 | if (delay > 0) {
83 | setTimeout(pageviewCallback, delay)
84 | } else {
85 | pageviewCallback()
86 | }
87 | }
88 |
89 | // "load" then "page" if necessary
90 | function loaderCallback (cb) {
91 | if (window.gatsbyPluginSegmentLoader) {
92 | window.gatsbyPluginSegmentLoader(cb);
93 | return true;
94 | }
95 | }
96 | };
97 |
--------------------------------------------------------------------------------
/src/gatsby-ssr.js:
--------------------------------------------------------------------------------
1 | // https://www.gatsbyjs.com/docs/reference/config-files/gatsby-ssr/
2 | import React from "react";
3 |
4 | export function onRenderBody({ setHeadComponents }, pluginOptions) {
5 | const {
6 | prodKey,
7 | devKey,
8 | host = "https://cdn.segment.io",
9 | trackPage = true,
10 | trackPageImmediately = true,
11 | trackPageOnlyIfReady = false,
12 | // This is ONLY for the Browser side code
13 | // trackPageOnRouteUpdate = true,
14 | // trackPageOnRouteUpdateDelay = 50,
15 | includeTitleInTrackPage,
16 | manualLoad = false,
17 | delayLoad = false,
18 | delayLoadDelay = 1000,
19 | delayLoadUntilActivity = false,
20 | delayLoadUntilActivityAdditionalDelay = 0,
21 | customSnippet,
22 | } = pluginOptions;
23 |
24 | let {
25 | trackPageWithTitle = false,
26 | } = pluginOptions;
27 |
28 | if (typeof includeTitleInTrackPage === 'boolean') {
29 | console.warn('WARNING: option for gatsby-plugin-segment "includeTitleInTrackPage" is deprecated. Please use "trackPageWithTitle" instead.')
30 | trackPageWithTitle = includeTitleInTrackPage
31 | }
32 |
33 | // ensures Segment write key is present
34 | if (!prodKey || prodKey.length < 10)
35 | console.error("segment prodKey must be at least 10 char in length");
36 |
37 | // if dev key is present, ensures it is at least 10 car in length
38 | if (devKey && devKey.length < 10)
39 | console.error("if present, devKey must be at least 10 char in length");
40 |
41 | // use prod write key when in prod env, else use dev write key
42 | // note below, snippet wont render unless writeKey is truthy
43 | const writeKey = process.env.NODE_ENV === "production" ? prodKey : devKey;
44 |
45 | const loadImmediately = !(delayLoad || delayLoadUntilActivity || manualLoad);
46 | const reallyTrackPageImmediately = trackPageImmediately && trackPage
47 |
48 | const idempotentPageviewCode = `(function () {
49 | let lastPageviewPath;
50 | window.gatsbyPluginSegmentPageviewCaller = function () {
51 | if (!window.analytics) {
52 | return
53 | }${ trackPageOnlyIfReady ? `
54 | if (!gatsbyPluginSegmentReady) {
55 | return
56 | }` : ''}
57 |
58 | let thisPageviewPath = window.location.pathname;
59 | if (thisPageviewPath === lastPageviewPath) {
60 | return
61 | }
62 | lastPageviewPath = thisPageviewPath;
63 | window.analytics.page(${ trackPageWithTitle ? 'document.title' : ''});
64 | };
65 | })();`;
66 |
67 | let delayedLoadingCode = `(function () {
68 | let segmentLoaded = false;
69 | let segmentLoading = false;
70 | const callbacks = [];
71 | function safeExecCallback (cb) {
72 | if (typeof cb === "function") {
73 | cb();
74 | }
75 | }
76 |
77 | window.gatsbyPluginSegmentLoader = function (cb) {
78 | if (segmentLoaded) {
79 | safeExecCallback(cb);
80 | return;
81 | }
82 |
83 | callbacks.push(cb);
84 | if (segmentLoading) {
85 | return;
86 | }
87 |
88 | segmentLoading = true;
89 |
90 | function loader() {
91 | if (typeof window.analytics.load !== "function") {
92 | console.error("Gatsby Plugin Segment: analytics.load is not a function. Has it already been called?");
93 | return
94 | }
95 | gatsbySegmentLoad('${writeKey}');
96 | segmentLoading = false;
97 | segmentLoaded = true;
98 | let cb;
99 | while ((cb = callbacks.pop()) != null) {
100 | safeExecCallback(cb);
101 | }${reallyTrackPageImmediately ? `
102 | window.gatsbyPluginSegmentPageviewCaller();` : ''}
103 | };
104 |
105 | if ("requestIdleCallback" in window) {
106 | requestIdleCallback(loader);
107 | } else {
108 | loader();
109 | }
110 | };`
111 | if (delayLoadUntilActivity) {
112 | delayedLoadingCode += `
113 | window.addEventListener(
114 | "scroll",
115 | function () {
116 | setTimeout(
117 | function () {
118 | window.gatsbyPluginSegmentLoader && window.gatsbyPluginSegmentLoader();
119 | },
120 | ${Math.max(0, delayLoadUntilActivityAdditionalDelay || 0)},
121 | )
122 | },
123 | { once: true },
124 | );`
125 | }
126 | if (delayLoad) {
127 | delayedLoadingCode += `
128 | setTimeout(
129 | function () {
130 | window.gatsbyPluginSegmentLoader && window.gatsbyPluginSegmentLoader();
131 | },
132 | ${delayLoadDelay || 1000},
133 | );`
134 | }
135 | delayedLoadingCode += `
136 | })();`;
137 |
138 | let snippet
139 | if (customSnippet) {
140 | snippet = eval('`' + customSnippet + '`')
141 | snippet += `
142 | window.analytics.ready(function () {
143 | gatsbyPluginSegmentReady = true;
144 | })
145 | `
146 | } else {
147 | // Segment's snippet (version 4.15.3)
148 | // If this is updated, probably good to update the README to include the version
149 | snippet = `(function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e,
188 | ]);
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/tests/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: '../.eslintrc.js',
3 | env: {
4 | mocha: true
5 | },
6 | plugins: [
7 | 'mocha',
8 | ],
9 | rules: {
10 | 'mocha/no-skipped-tests': 'error',
11 | 'mocha/no-exclusive-tests': 'error',
12 | },
13 | globals: {
14 | expect: 'readonly',
15 | pathToProject: 'readonly'
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/gatsby-2/gatsby-config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Configure your Gatsby site with this file.
3 | *
4 | * See: https://www.gatsbyjs.com/docs/gatsby-config/
5 | */
6 |
7 | module.exports = {
8 | /* Your site config here */
9 | plugins: [
10 | {
11 | resolve: `gatsby-plugin-segment-js`,
12 | options: {
13 | prodKey: `ADD_API_KEY_PROD`,
14 | devKey: `ADD_API_KEY_DEV`,
15 | trackPage: true
16 | }
17 | },
18 | ],
19 | }
20 |
--------------------------------------------------------------------------------
/tests/gatsby-2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-plugin-segment-js-test-gatsby-2",
3 | "private": true,
4 | "description": "A simple Gatsby app to test the plugin with Gatsby 2",
5 | "version": "0.1.0",
6 | "license": "0BSD",
7 | "scripts": {
8 | "build": "gatsby build",
9 | "develop": "gatsby develop",
10 | "clean": "gatsby clean",
11 | "plugin": "yarn plugin:build && yarn plugin:install",
12 | "plugin:build": "yarn --cwd ../.. build-n-pack",
13 | "plugin:remove": "yarn remove gatsby-plugin-segment-js",
14 | "plugin:install": "yarn add ../../gatsby-plugin-segment-js.tgz",
15 | "test": "yarn test:prepare && yarn test:run",
16 | "test:prepare": "yarn plugin && yarn clean && yarn build",
17 | "test:run": "mocha --config ./test/mocha-config.js"
18 | },
19 | "dependencies": {
20 | "gatsby": "^2",
21 | "gatsby-plugin-segment-js": "../../gatsby-plugin-segment-js.tgz",
22 | "react": "^16.12.0",
23 | "react-dom": "^16.12.0"
24 | },
25 | "devDependencies": {
26 | "chai": "^4.3.4",
27 | "mocha": "^9.1.3"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/gatsby-2/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | export default function Home() {
4 | return