mirror of
https://github.com/kremalicious/gatsby-plugin-matomo.git
synced 2024-12-22 09:13:19 +01:00
Merge pull request #21 from kremalicious/feature/updates
Updates, cleanup, and testing
This commit is contained in:
commit
f5a0180b98
5
.babelrc
5
.babelrc
@ -1,6 +1,3 @@
|
||||
{
|
||||
"presets": [
|
||||
["@babel/env"],
|
||||
["@babel/react"]
|
||||
]
|
||||
"presets": [["babel-preset-gatsby-package", { "browser": true }]]
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
version: "2"
|
||||
checks:
|
||||
method-lines:
|
||||
config:
|
||||
threshold: 40
|
@ -1,10 +0,0 @@
|
||||
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
11
.eslintrc
11
.eslintrc
@ -1,10 +1,6 @@
|
||||
{
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"plugins": ["react", "prettier"],
|
||||
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
|
||||
"plugins": ["prettier"],
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
@ -15,6 +11,7 @@
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es6": true
|
||||
"es6": true,
|
||||
"jest": true
|
||||
}
|
||||
}
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/*.js
|
||||
node_modules
|
||||
package-lock.json
|
||||
coverage
|
@ -4,3 +4,5 @@ src
|
||||
.editorconfig
|
||||
.eslintrc
|
||||
.travis.yml
|
||||
coverage
|
||||
__tests__
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none"
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2
|
||||
}
|
||||
|
14
.travis.yml
14
.travis.yml
@ -1,5 +1,17 @@
|
||||
language: node_js
|
||||
node_js: node
|
||||
|
||||
before_script:
|
||||
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
||||
- chmod +x ./cc-test-reporter
|
||||
- ./cc-test-reporter before-build
|
||||
|
||||
script:
|
||||
- npm test
|
||||
- npm run build
|
||||
|
||||
after_script:
|
||||
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
email: false
|
||||
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2018 Matthias Kretschmann m@kretschmann.io
|
||||
Copyright (c) 2020 Matthias Kretschmann m@kretschmann.io
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
[![npm package](https://img.shields.io/npm/v/gatsby-plugin-matomo.svg)](https://www.npmjs.com/package/gatsby-plugin-matomo)
|
||||
[![Build Status](https://travis-ci.com/kremalicious/gatsby-plugin-matomo.svg?branch=master)](https://travis-ci.com/kremalicious/gatsby-plugin-matomo)
|
||||
[![Maintainability](https://api.codeclimate.com/v1/badges/067339a02f2058f5ba01/maintainability)](https://codeclimate.com/github/kremalicious/gatsby-plugin-matomo/maintainability)
|
||||
[![Test Coverage](https://api.codeclimate.com/v1/badges/067339a02f2058f5ba01/test_coverage)](https://codeclimate.com/github/kremalicious/gatsby-plugin-matomo/test_coverage)
|
||||
[![Greenkeeper badge](https://badges.greenkeeper.io/kremalicious/gatsby-plugin-matomo.svg)](https://greenkeeper.io/)
|
||||
|
||||
> 🥂 Gatsby plugin to add Matomo (formerly Piwik) onto a site. https://kremalicious.com/gatsby-plugin-matomo/
|
||||
@ -82,7 +83,7 @@ plugins: [
|
||||
options: {
|
||||
siteId: 'YOUR_SITE_ID',
|
||||
matomoUrl: 'https://YOUR_MATOMO_URL.COM',
|
||||
siteUrl: 'https://YOUR_LIVE_SITE_URL.COM'
|
||||
siteUrl: 'https://YOUR_LIVE_SITE_URL.COM',
|
||||
// All the optional settings
|
||||
exclude: ['/offline-plugin-app-shell-fallback/'],
|
||||
requireConsent: false,
|
||||
@ -118,7 +119,7 @@ See [CHANGELOG.md](CHANGELOG.md).
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2018 Matthias Kretschmann
|
||||
Copyright (c) 2020 Matthias Kretschmann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
44
package.json
44
package.json
@ -4,42 +4,46 @@
|
||||
"version": "0.7.2",
|
||||
"author": "Matthias Kretschmann <m@kretschmann.io>",
|
||||
"scripts": {
|
||||
"build": "babel src --out-dir . --ignore __tests__",
|
||||
"start": "babel -w src --out-dir . --ignore __tests__",
|
||||
"test": "eslint ./src/**/*.js",
|
||||
"format": "prettier --write 'src/**/*.{js,jsx}'",
|
||||
"build": "babel src --out-dir . --ignore **/__tests__",
|
||||
"start": "babel -w src --out-dir . --ignore **/__tests__",
|
||||
"test": "npm run lint && jest --coverage",
|
||||
"lint": "eslint ./src/**/*.js",
|
||||
"format": "prettier --write 'src/**/*.js'",
|
||||
"release": "release-it --non-interactive",
|
||||
"changelog": "auto-changelog -p",
|
||||
"prepublishOnly": "cross-env NODE_ENV=production npm run build"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.4.4",
|
||||
"@babel/core": "^7.4.5",
|
||||
"@babel/preset-env": "^7.4.5",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"auto-changelog": "^1.13.0",
|
||||
"cross-env": "^5.2.0",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-prettier": "^4.3.0",
|
||||
"eslint-plugin-prettier": "^3.1.0",
|
||||
"eslint-plugin-react": "^7.13.0",
|
||||
"prettier": "^1.18.2",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"release-it": "^12.3.0"
|
||||
"@babel/cli": "^7.8.4",
|
||||
"@babel/core": "^7.8.4",
|
||||
"@babel/runtime": "^7.8.4",
|
||||
"auto-changelog": "^1.16.2",
|
||||
"babel-preset-gatsby-package": "^0.2.16",
|
||||
"cross-env": "^7.0.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-prettier": "^6.10.0",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"jest": "^25.1.0",
|
||||
"prettier": "^1.19.1",
|
||||
"react": "^16.12.0",
|
||||
"release-it": "^12.4.3"
|
||||
},
|
||||
"homepage": "https://github.com/kremalicious/gatsby-plugin-matomo",
|
||||
"homepage": "https://kremalicious.com/gatsby-plugin-matomo",
|
||||
"keywords": [
|
||||
"gatsby",
|
||||
"gatsby-plugin",
|
||||
"analytics",
|
||||
"tracking",
|
||||
"matomo",
|
||||
"piwik"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"peerDependencies": {
|
||||
"gatsby": ">=1.9.0"
|
||||
"gatsby": ">=2.0.0",
|
||||
"react": ">=16.4.2",
|
||||
"react-dom": ">=16.4.2"
|
||||
},
|
||||
"repository": "github:kremalicious/gatsby-plugin-matomo",
|
||||
"bugs": {
|
||||
|
66
src/__tests__/gatsby-browser.js
Normal file
66
src/__tests__/gatsby-browser.js
Normal file
@ -0,0 +1,66 @@
|
||||
import { onRouteUpdate } from '../gatsby-browser'
|
||||
|
||||
describe('gatsby-plugin-matomo', () => {
|
||||
describe('gatsby-browser', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers()
|
||||
window._paq = { push: jest.fn() }
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks()
|
||||
})
|
||||
|
||||
describe('onRouteUpdate', () => {
|
||||
describe('in non-production env', () => {
|
||||
beforeAll(() => {
|
||||
window._paq = { push: jest.fn() }
|
||||
})
|
||||
|
||||
it('does not send page view', () => {
|
||||
onRouteUpdate({})
|
||||
expect(window._paq.push).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('sends page view in dev mode', () => {
|
||||
window.dev = true
|
||||
onRouteUpdate({})
|
||||
expect(window._paq.push).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('in production env', () => {
|
||||
let env
|
||||
|
||||
beforeAll(() => {
|
||||
env = process.env.NODE_ENV
|
||||
process.env.NODE_ENV = 'production'
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
process.env.NODE_ENV = env
|
||||
})
|
||||
|
||||
it('does not send page view when _paq is undefined', () => {
|
||||
delete window._paq
|
||||
onRouteUpdate({})
|
||||
jest.runAllTimers()
|
||||
expect(setTimeout).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('sends page view', () => {
|
||||
onRouteUpdate({})
|
||||
jest.runAllTimers()
|
||||
expect(window._paq.push).toHaveBeenCalledTimes(5)
|
||||
})
|
||||
|
||||
it('uses setTimeout with a minimum delay of 32ms', () => {
|
||||
onRouteUpdate({})
|
||||
jest.runAllTimers()
|
||||
expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 32)
|
||||
expect(window._paq.push).toHaveBeenCalledTimes(5)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
74
src/__tests__/gatsby-ssr.js
Normal file
74
src/__tests__/gatsby-ssr.js
Normal file
@ -0,0 +1,74 @@
|
||||
import { onRenderBody } from '../gatsby-ssr'
|
||||
|
||||
describe('gatsby-plugin-google-analytics', () => {
|
||||
describe('gatsby-ssr', () => {
|
||||
describe('onRenderBody', () => {
|
||||
describe('in non-production env', () => {
|
||||
it('does not set tracking script', () => {
|
||||
const setHeadComponents = jest.fn()
|
||||
onRenderBody({ setHeadComponents })
|
||||
expect(setHeadComponents).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('in production env', () => {
|
||||
let env
|
||||
|
||||
beforeAll(() => {
|
||||
env = process.env.NODE_ENV
|
||||
process.env.NODE_ENV = 'production'
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
process.env.NODE_ENV = env
|
||||
})
|
||||
|
||||
const setup = options => {
|
||||
const setHeadComponents = jest.fn()
|
||||
const setPostBodyComponents = jest.fn()
|
||||
|
||||
options = Object.assign(
|
||||
{
|
||||
siteId: 'TEST_SITE_ID',
|
||||
matomoUrl: 'TEST_MATOMO_URL',
|
||||
siteUrl: 'TEST_SITE_URL'
|
||||
},
|
||||
options
|
||||
)
|
||||
|
||||
onRenderBody({ setHeadComponents, setPostBodyComponents }, options)
|
||||
|
||||
return {
|
||||
setHeadComponents,
|
||||
setPostBodyComponents
|
||||
}
|
||||
}
|
||||
|
||||
it('sets tracking script', () => {
|
||||
const { setHeadComponents, setPostBodyComponents } = setup()
|
||||
|
||||
expect(setHeadComponents).toHaveBeenCalledTimes(1)
|
||||
expect(setPostBodyComponents).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('sets siteId', () => {
|
||||
const { setPostBodyComponents } = setup()
|
||||
const result = JSON.stringify(setPostBodyComponents.mock.calls[0][0])
|
||||
expect(result).toMatch(/TEST_SITE_ID/)
|
||||
})
|
||||
|
||||
it('sets matomoUrl', () => {
|
||||
const { setPostBodyComponents } = setup()
|
||||
const result = JSON.stringify(setPostBodyComponents.mock.calls[0][0])
|
||||
expect(result).toMatch(/TEST_MATOMO_URL/)
|
||||
})
|
||||
|
||||
it('sets siteUrl', () => {
|
||||
const { setPostBodyComponents } = setup()
|
||||
const result = JSON.stringify(setPostBodyComponents.mock.calls[0][0])
|
||||
expect(result).toMatch(/TEST_SITE_URL/)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@ -1,5 +1,3 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
let first = true
|
||||
|
||||
function getDuration() {
|
||||
@ -14,15 +12,12 @@ function getDuration() {
|
||||
return difference
|
||||
}
|
||||
|
||||
exports.onRouteUpdate = ({ location, prevLocation }) => {
|
||||
if (
|
||||
(process.env.NODE_ENV === 'production' && typeof _paq !== 'undefined') ||
|
||||
window.dev === true
|
||||
) {
|
||||
const _paq = window._paq || []
|
||||
const dev = window.dev || null
|
||||
export const onRouteUpdate = ({ location, prevLocation }) => {
|
||||
if (process.env.NODE_ENV === 'production' || window.dev === true) {
|
||||
if (!window._paq) return
|
||||
|
||||
const url = location.pathname + location.search + location.hash
|
||||
const { _paq, dev } = window
|
||||
const url = location && location.pathname + location.search + location.hash
|
||||
const prevUrl =
|
||||
prevLocation &&
|
||||
prevLocation.pathname + prevLocation.search + prevLocation.hash
|
||||
@ -40,27 +35,23 @@ exports.onRouteUpdate = ({ location, prevLocation }) => {
|
||||
_paq.push(['trackAllContentImpressions'])
|
||||
|
||||
if (dev) {
|
||||
console.log(`[Matomo] Page view for: ${url} - ${title}`)
|
||||
console.debug(`[Matomo] Page view for: ${url} - ${title}`)
|
||||
}
|
||||
}
|
||||
|
||||
if ('requestAnimationFrame' in window) {
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(sendPageView)
|
||||
})
|
||||
} else {
|
||||
// simulate 2 rAF calls
|
||||
setTimeout(sendPageView, 32)
|
||||
}
|
||||
// Minimum delay for reactHelmet's requestAnimationFrame
|
||||
const delay = Math.max(32, 0)
|
||||
setTimeout(sendPageView, delay)
|
||||
|
||||
if (first) {
|
||||
first = false
|
||||
_paq.push(['trackEvent', 'javascript', 'load', 'duration', getDuration()])
|
||||
|
||||
if (dev) {
|
||||
console.log(`[Matomo] Tracking duration for: ${url}`)
|
||||
console.debug(`[Matomo] Tracking duration for: ${url}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import React from 'react'
|
||||
|
||||
function buildTrackingCode(pluginOptions) {
|
||||
@ -29,29 +30,28 @@ function buildTrackingCode(pluginOptions) {
|
||||
})();
|
||||
|
||||
if (window.dev === true) {
|
||||
console.log('[Matomo] Tracking initialized')
|
||||
console.log('[Matomo] matomoUrl: ${matomoUrl}, siteId: ${siteId}')
|
||||
console.debug('[Matomo] Tracking initialized')
|
||||
console.debug('[Matomo] matomoUrl: ${matomoUrl}, siteId: ${siteId}')
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
return (
|
||||
<script
|
||||
key={'gatsby-plugin-matomo'}
|
||||
key="script-gatsby-plugin-matomo"
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function buildTrackingCodeNoJs(pluginOptions, pathname) {
|
||||
const html = `<img src="${pluginOptions.matomoUrl}/piwik.php?idsite=${
|
||||
pluginOptions.siteId
|
||||
}&rec=1&url=${pluginOptions.siteUrl +
|
||||
const { matomoUrl, siteId, siteUrl } = pluginOptions
|
||||
const html = `<img src="${matomoUrl}/piwik.php?idsite=${siteId}&rec=1&url=${siteUrl +
|
||||
pathname}" style="border:0" alt="tracker" />`
|
||||
|
||||
return (
|
||||
<noscript
|
||||
key={'gatsby-plugin-matomo'}
|
||||
key="noscript-gatsby-plugin-matomo"
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
/>
|
||||
)
|
||||
@ -62,18 +62,19 @@ function buildHead(pluginOptions) {
|
||||
<link
|
||||
rel="preconnect"
|
||||
href={pluginOptions.matomoUrl}
|
||||
key={'gatsby-plugin-matomo'}
|
||||
key="preconnect-gatsby-plugin-matomo"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
exports.onRenderBody = (
|
||||
export const onRenderBody = (
|
||||
{ setHeadComponents, setPostBodyComponents, pathname },
|
||||
pluginOptions
|
||||
) => {
|
||||
const isProduction = process.env.NODE_ENV === 'production'
|
||||
let excludePaths = ['/offline-plugin-app-shell-fallback/']
|
||||
|
||||
if (typeof pluginOptions.exclude !== 'undefined') {
|
||||
if (pluginOptions && typeof pluginOptions.exclude !== 'undefined') {
|
||||
pluginOptions.exclude.map(exclude => {
|
||||
excludePaths.push(exclude)
|
||||
})
|
||||
@ -82,7 +83,7 @@ exports.onRenderBody = (
|
||||
const isPathExcluded = excludePaths.some(path => pathname === path)
|
||||
|
||||
if (
|
||||
(process.env.NODE_ENV === 'production' || pluginOptions.dev === true) &&
|
||||
(isProduction || (pluginOptions && pluginOptions.dev === true)) &&
|
||||
!isPathExcluded
|
||||
) {
|
||||
setHeadComponents([buildHead(pluginOptions)])
|
||||
|
Loading…
Reference in New Issue
Block a user