Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow opting into analytics #101

Merged
merged 23 commits into from
Jan 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6b8e8b9
Mainly copy-paste the Settings page PHP to the free plugin
kienstra Dec 9, 2021
659f77f
Correct 2 package tags to be for free, not pro
kienstra Dec 9, 2021
0b75e3d
Change node version to 14.18.1, see if that makes builds pass
kienstra Nov 12, 2021
96f2872
Change .nvmrc to 14, as lts is now 16
kienstra Dec 9, 2021
6c9b39c
Move the settings registration to the top of Admin class
kienstra Dec 14, 2021
80db35c
Change the settings group name to align with what it does
kienstra Dec 14, 2021
ae67220
Add a Settings.php view, copied from the Pro plugin
kienstra Dec 14, 2021
9a204a5
Enqueue the analytics script if opted-in, props BMO
kienstra Dec 15, 2021
16e8841
Add a test for having opted into analytics
kienstra Dec 15, 2021
2fd92f4
Bump copyright dates that I should have bumped earlier
kienstra Dec 15, 2021
ce0791a
Copy BMO's wp_localize_script() call
kienstra Dec 15, 2021
7a6a566
Copy BMO's GAClient into GCB
kienstra Dec 15, 2021
1848697
Instantiate GAClient in the GCB editor and the block editor
kienstra Dec 15, 2021
8e4d34f
Remove the GB Analytics ID, add Todo to replace with a unique one for…
kienstra Dec 15, 2021
459f339
Change window.GenesisAnalytics to not conflict with Genesis Blocks
kienstra Dec 15, 2021
c5eb1d3
Move the analytics bootstrapping inside domReady()
kienstra Dec 15, 2021
4c6b41b
Acknowledge BMO's work in debounce()
kienstra Dec 15, 2021
0b2f869
Change some copypasta: this was copied from a Subscription page
kienstra Dec 15, 2021
7c00b23
Acknowledge BMO's work in the GAClient
kienstra Dec 16, 2021
40cd3de
Make comment format more like GCB's comments
kienstra Dec 16, 2021
b45e3a3
Change genesisAnalyticsConfig to gcbAnalyticsConfig
kienstra Dec 16, 2021
87d1f45
Change genesisAnalyticsConfig to gcbAnalyticsConfig
kienstra Dec 16, 2021
9d8bd80
Move window.dataLayer assignment back into the class file
kienstra Dec 16, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
steps:
- checkout
- node/install:
node-version: lts
node-version: '14.18.1'
- nodegit-workaround
- set-up-packages
- run: npm run lint
Expand Down Expand Up @@ -67,7 +67,7 @@ jobs:
sudo apt-get update && sudo apt-get install libpng-dev
sudo docker-php-ext-install mysqli gd
- node/install:
node-version: lts
node-version: '14.18.1'
- nodegit-workaround
- run:
name: Installing WordPress and setting up tests
Expand All @@ -94,7 +94,7 @@ jobs:
steps:
- checkout
- node/install:
node-version: lts
node-version: '14.18.1'
- nodegit-workaround
- run: HUSKY_SKIP_INSTALL=1 npm ci && npm run test:js -- --maxWorkers=2

Expand All @@ -106,7 +106,7 @@ jobs:
- run: sudo apt-get update && sudo apt-get install php php-xml
- install-composer
- node/install:
node-version: lts
node-version: '14.18.1'
- nodegit-workaround
- set-up-packages
- run: npm run wp-env start && npm run test:e2e
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
lts/*
14
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node LTS used to be 14, but now it's 16. It seems that Gutenberg still uses 14

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting! I haven't heard of this lts before.

10 changes: 9 additions & 1 deletion js/src/block-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,23 @@
/**
* WordPress dependencies
*/
import { setLocaleData } from '@wordpress/i18n';
import { addFilter } from '@wordpress/hooks';
import { setLocaleData } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { addControls, registerBlocks } from './helpers';
import { Edit } from './components';
import { GAClient } from '../common/classes';

setLocaleData( { '': {} }, 'genesis-custom-blocks' );
addFilter( 'genesisCustomBlocks.controls', 'genesisCustomBlocks/addControls', addControls );

// @ts-ignore
registerBlocks( genesisCustomBlocks, gcbBlocks, Edit );

// @ts-ignore
window.GcbAnalytics = {
GAClient: new GAClient(),
};
103 changes: 103 additions & 0 deletions js/src/common/classes/GAClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* Internal dependencies
*/
import { debounce } from '../helpers';

// @ts-ignore
window.dataLayer = window.dataLayer || [];

/**
* Genesis Analytics Client
*
* Forked from BMO's work in Genesis Blocks.
*
* Follows the singleton pattern to prevent multiple instances of the GA Client from being used.
* https://developers.google.com/analytics/devguides/collection/gtagjs
*/
export default class GAClient {
/**
* Is Google Analytics enabled.
*
* @type {boolean}
*/
enabled = false;

/**
* Google Analytics Client
*
* @type {Object}
*/
client;

/**
* Google Analytics Measurment ID.
*
* Todo: update this for GCB.
*
* @type {string}
*/
GA_ID = 'UA-12345';

/**
* Class constructor.
*/
constructor() {
this.client = function() {
// @ts-ignore
window.dataLayer.push( arguments );
};

// @ts-ignore
this.config = window.gcbAnalyticsConfig || {};
if ( this.config.ga_opt_in ) {
this.enableAnalytics( this.config.ga_opt_in );
this.initClient();
}
}

/**
* Enables Google Analytics.
* Setting this value allows the GA Client to respect any opt out configuration.
*
* https://developers.google.com/analytics/devguides/collection/gtagjs/user-opt-out
*
* @param {boolean | number | string} enable The value to be set.
*/
enableAnalytics( enable ) {
enable = !! +enable;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I'm familiar with this syntax. What is happening on this line?

Copy link
Contributor Author

@kienstra kienstra Dec 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I stole that from BMO.

I didn't know about + either.

It's first casting enable to a Number with +enable. For example, converting '0' to 0.

Then, it casts it to a Boolean with !!.

I think this prevents an enable value of '0' from being true.

Like:

if ( '0' ) {
    console.log( 'This is true' );
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course! I just found out about +


if ( enable ) {
// Remove ga-disable-GA_MEASUREMENT_ID property to enable GA.
delete window[ `ga-disable-${ this.GA_ID }` ];
} else {
// Set ga-disable-GA_MEASUREMENT_ID property to disable GA.
window[ `ga-disable-${ this.GA_ID }` ] = '1';
}
this.enabled = enable;
}

/**
* Sets up the initial values of the Google Analytics client.
*/
initClient() {
this.client( 'js', new Date() );
this.client( 'config', this.GA_ID, { send_page_view: false } );
}

/**
* Sends an event to Google Analytics.
*
* @param {string} action
* @param {{event_category: string; event_label?: string;}} params
*/
send( action, params ) {
if ( this.enabled ) {
this.client( 'event', action, params );
}
}

/**
* Creates a debounced copy of send method.
*/
sendDebounce = debounce( this.send.bind( this ), 500 );
}
1 change: 1 addition & 0 deletions js/src/common/classes/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as GAClient } from './GAClient';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is silly for one file, but it follows the pattern of exporting files in all of the other directories

24 changes: 24 additions & 0 deletions js/src/common/helpers/debounce.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Ensures that the provided function isn't called multiple times in succession.
*
* Forked from BMO's work in Genesis Blocks.
*
* @param {() => any} func
* @param {number} wait
*
* @return {() => void} A debounced function.
*/
const debounce = ( func, wait ) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't follow the same standard as the rest of this plugin, but it is possible to name the export instead of using default.

export const debounce = () => { ... }

That will prevent the need for export default debounce at the bottom, and it can be included with

include { debounce }  from './debounce';

Copy link
Contributor Author

@kienstra kienstra Dec 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this plugin's setup is a bit outdated, with the index.js file having all of the exports.

Ideally, I'd modernize the whole js/src directory.

But it might be strange to not have this debounce in index.js, while all of the other helper functions are in it.

let timeout;
return function executedFunction( ...args ) {
const later = () => {
clearTimeout( timeout );
func( ...args );
};

clearTimeout( timeout );
timeout = setTimeout( later, wait );
};
};

export default debounce;
1 change: 1 addition & 0 deletions js/src/common/helpers/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as debounce } from './debounce';
export { default as getFieldsAsArray } from './getFieldsAsArray';
export { default as getFieldsAsObject } from './getFieldsAsObject';
export { default as getIconComponent } from './getIconComponent';
Expand Down
8 changes: 7 additions & 1 deletion js/src/edit-block/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { addFilter } from '@wordpress/hooks';
*/
import { initializeEditor } from './helpers';
import { addControls } from '../block-editor/helpers';
import { GAClient } from '../common/classes';

addFilter( 'genesisCustomBlocks.controls', 'genesisCustomBlocks/addControls', addControls );

// Renders the app in the container.
domReady( () => {
Expand All @@ -23,4 +26,7 @@ domReady( () => {
initializeEditor( gcbEditor, container );
} );

addFilter( 'genesisCustomBlocks.controls', 'genesisCustomBlocks/addControls', addControls );
// @ts-ignore
window.GcbAnalytics = {
GAClient: new GAClient(),
};
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
"bugs": {
"url": "https://github.com/studiopress/genesis-custom-blocks/issues"
},
"engines": {
"node": "14"
},
"devDependencies": {
"@material-ui/core": "4.11.2",
"@material-ui/icons": "4.11.2",
Expand Down
16 changes: 13 additions & 3 deletions php/Admin/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
*/
class Admin extends ComponentAbstract {

/**
* Plugin settings.
*
* @var Settings
*/
public $settings;

/**
* Plugin documentation.
*
Expand Down Expand Up @@ -55,18 +62,21 @@ class Admin extends ComponentAbstract {
* Initialise the Admin component.
*/
public function init() {
$this->settings = new Settings();
genesis_custom_blocks()->register_component( $this->settings );

$this->documentation = new Documentation();
genesis_custom_blocks()->register_component( $this->documentation );

$this->edit_block = new EditBlock();
genesis_custom_blocks()->register_component( $this->edit_block );

$this->onboarding = new Onboarding();
genesis_custom_blocks()->register_component( $this->onboarding );

$this->upgrade = new Upgrade();
genesis_custom_blocks()->register_component( $this->upgrade );

$this->edit_block = new EditBlock();
genesis_custom_blocks()->register_component( $this->edit_block );

if ( defined( 'WP_LOAD_IMPORTERS' ) && WP_LOAD_IMPORTERS ) {
$this->import = new Import();
genesis_custom_blocks()->register_component( $this->import );
Expand Down
89 changes: 89 additions & 0 deletions php/Admin/Settings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
/**
* Genesis Custom Blocks Settings.
*
* @package Genesis\CustomBlocks
* @copyright Copyright(c) 2021, Genesis Custom Blocks
* @license http://opensource.org/licenses/GPL-2.0 GNU General Public License, version 2 (GPL-2.0)
*/

namespace Genesis\CustomBlocks\Admin;

use Genesis\CustomBlocks\ComponentAbstract;

/**
* Class Settings
*/
class Settings extends ComponentAbstract {

/**
* Option name for the notices.
*
* @var string
*/
const NOTICES_OPTION_NAME = 'genesis_custom_blocks_notices';

/**
* Settings group to opt into analytics.
*
* @var string
*/
const SETTINGS_GROUP = 'genesis-custom-blocks-settings-page';

/**
* Option name to opt into analytics.
*
* @var string
*/
const ANALYTICS_OPTION_NAME = 'genesis_custom_blocks_analytics_opt_in';

/**
* The value when a user has opted into analytics.
*
* @var string
*/
const ANALYTICS_OPTED_IN_VALUE = 'genesis_custom_blocks_analytics_opt_in';

/**
* Page slug.
*
* @var string
*/
const PAGE_SLUG = 'genesis-custom-blocks-settings';

/**
* Register any hooks that this component needs.
*/
public function register_hooks() {
add_action( 'admin_menu', [ $this, 'add_submenu_pages' ] );
add_action( 'admin_init', [ $this, 'register_settings' ] );
}

/**
* Add submenu pages to the Genesis Custom Blocks menu.
*/
public function add_submenu_pages() {
add_submenu_page(
'edit.php?post_type=' . genesis_custom_blocks()->get_post_type_slug(),
__( 'Genesis Custom Blocks Settings', 'genesis-custom-blocks' ),
__( 'Settings', 'genesis-custom-blocks' ),
'manage_options',
self::PAGE_SLUG,
[ $this, 'render_page' ]
);
}

/**
* Renders the Settings page.
*/
public function render_page() {
include genesis_custom_blocks()->get_path() . 'php/Views/Settings.php';
}

/**
* Register Genesis Custom Blocks settings.
*/
public function register_settings() {
register_setting( self::SETTINGS_GROUP, self::ANALYTICS_OPTION_NAME );
}
}
Loading