Skip to content

Commit

Permalink
Add Tracks Analytics on frontend (#185)
Browse files Browse the repository at this point in the history
Add Tracks Analytics by using the `@automattic/calypso-analytics` package. With each track event, the following properties will be tracked:

- Properties related to VIP Platform (e.g. org_id, env_id).
- Properties related to Remote Data Blocks (e.g. plugin_version).
- Event specific properties.

**Note:** This tracking will only work if site is hosted on VIP Platform or if the analytics is enabled via filter.
  • Loading branch information
mehmoodak authored Nov 15, 2024
1 parent 9c1c659 commit ad58e6b
Show file tree
Hide file tree
Showing 28 changed files with 365 additions and 46 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ module.exports = {
extends: [ 'plugin:@automattic/wpvip/recommended' ],
globals: {
REMOTE_DATA_BLOCKS: 'readonly',
REMOTE_DATA_BLOCKS_SETTINGS: 'readonly',
},
};
4 changes: 2 additions & 2 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
if [ -d "$(git rev-parse --git-path rebase-merge)" ] || [ -d "$(git rev-parse --git-path rebase-apply)" ]; then
echo "Rebase in progress. Skipping pre-commit hook.\n";
exit 0;
echo "Rebase in progress. Skipping pre-commit hook.\n"
exit 0
fi

lint-staged
2 changes: 1 addition & 1 deletion .lintstagedrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"*.css": [ "npm run lint:css" ],
"*.{js,jsx,ts,tsx}": [ "npm run lint:js" ],
"*.{js,jsx,ts,tsx}": [ "npm run lint" ],
"*.php": [ "npm run lint:php" ],
"*.{js,json,jsx,md,ts,tsx,yml,yaml}": [ "npm run format:check" ]
}
3 changes: 3 additions & 0 deletions inc/Editor/BlockManagement/BlockRegistration.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

defined( 'ABSPATH' ) || exit();

use RemoteDataBlocks\Analytics\TracksAnalytics;
use RemoteDataBlocks\Editor\BlockPatterns\BlockPatterns;
use RemoteDataBlocks\Editor\DataBinding\BlockBindings;
use RemoteDataBlocks\REST\RemoteDataController;
Expand Down Expand Up @@ -77,6 +78,7 @@ public static function register_blocks(): void {
'availableBindings' => $available_bindings,
'loop' => $config['loop'],
'name' => $block_name,
'dataSourceType' => ConfigStore::get_data_source_type( $block_name ),
'overrides' => $formatted_overrides,
'patterns' => $config['patterns'],
'selectors' => $config['selectors'],
Expand Down Expand Up @@ -110,6 +112,7 @@ public static function register_blocks(): void {
wp_localize_script( $script_handle, 'REMOTE_DATA_BLOCKS', [
'config' => $remote_data_blocks_config,
'rest_url' => RemoteDataController::get_url(),
'tracks_global_properties' => TracksAnalytics::get_global_properties(),
] );
}
}
Expand Down
61 changes: 47 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"lint:fix": "npm run cmd:lint . -- --fix",
"lint:css:fix": "wp-scripts lint-style --fix",
"lint:css": "wp-scripts lint-style",
"lint:js": "npm run lint && npm run check-types",
"lint:js": "npm run lint",
"lint:php": "npm run lint:phpcs && npm run lint:psalm",
"lint:phpcs": "vendor/bin/phpcs --cache",
"lint:phpcs:fix": "vendor/bin/phpcbf",
Expand Down Expand Up @@ -99,5 +99,8 @@
},
"stylelint": {
"extends": "./node_modules/@wordpress/scripts/config/.stylelintrc.json"
},
"dependencies": {
"@automattic/calypso-analytics": "^1.1.2"
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { CheckboxControl, SelectControl } from '@wordpress/components';

import { TEXT_FIELD_TYPES } from '@/blocks/remote-data-container/config/constants';
import { sendTracksEvent } from '@/blocks/remote-data-container/utils/tracks';
import { getBlockDataSourceType } from '@/utils/localized-block-data';

interface BlockBindingFieldControlProps {
availableBindings: AvailableBindings;
Expand Down Expand Up @@ -35,12 +37,14 @@ interface BlockBindingControlsProps {
attributes: RemoteDataInnerBlockAttributes;
availableBindings: AvailableBindings;
blockName: string;
remoteDataName: string;
removeBinding: ( target: string ) => void;
updateBinding: ( target: string, args: Omit< RemoteDataBlockBindingArgs, 'block' > ) => void;
}

export function BlockBindingControls( props: BlockBindingControlsProps ) {
const { attributes, availableBindings, blockName, removeBinding, updateBinding } = props;
const { attributes, availableBindings, blockName, remoteDataName, removeBinding, updateBinding } =
props;
const contentArgs = attributes.metadata?.bindings?.content?.args;
const contentField = contentArgs?.field ?? '';
const imageAltField = attributes.metadata?.bindings?.alt?.args?.field ?? '';
Expand All @@ -51,11 +55,23 @@ export function BlockBindingControls( props: BlockBindingControlsProps ) {
function updateFieldBinding( target: string, field: string ): void {
if ( ! field ) {
removeBinding( target );
sendTracksEvent( 'remotedatablocks_remote_data_container_actions', {
action: 'remove_binding',
data_source_type: getBlockDataSourceType( remoteDataName ),
block_target_attribute: target,
} );

return;
}

const args = attributes.metadata?.bindings?.[ target ]?.args ?? {};
updateBinding( target, { ...args, field } );
sendTracksEvent( 'remotedatablocks_remote_data_container_actions', {
action: 'update_binding',
data_source_type: getBlockDataSourceType( remoteDataName ),
remote_data_field: field,
block_target_attribute: target,
} );
}

function updateFieldLabel( showLabel: boolean ): void {
Expand All @@ -68,6 +84,10 @@ export function BlockBindingControls( props: BlockBindingControlsProps ) {
? Object.entries( availableBindings ).find( ( [ key ] ) => key === contentField )?.[ 1 ]?.name
: undefined;
updateBinding( 'content', { ...contentArgs, field: contentField, label } );
sendTracksEvent( 'remotedatablocks_remote_data_container_actions', {
action: showLabel ? 'show_label' : 'hide_label',
data_source_type: getBlockDataSourceType( remoteDataName ),
} );
}

switch ( blockName ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
import { FieldShortcodeSelectFieldPopover } from '@/blocks/remote-data-container/components/field-shortcode/FieldShortcodeSelectFieldPopover';
import { FieldShortcodeSelectTabs } from '@/blocks/remote-data-container/components/field-shortcode/FieldShortcodeSelectTabs';
import { FieldShortcodeSelectField } from '@/blocks/remote-data-container/components/field-shortcode/FieldShortcodeSelection';
import { sendTracksEvent } from '@/blocks/remote-data-container/utils/tracks';
import { getBlockDataSourceType } from '@/utils/localized-block-data';

function parseDataQuery( dataQuery?: string ): FieldSelection | null {
if ( ! dataQuery ) {
Expand Down Expand Up @@ -38,6 +40,7 @@ export function FieldShortcodeButton( props: WPFormatEditProps ) {

function onClick() {
setShowUI( ! showUI );
sendTracksEvent( 'remotedatablocks_field_shortcode', { action: 'toolbar_icon_clicked' } );
}

function onClose() {
Expand Down Expand Up @@ -76,11 +79,20 @@ export function FieldShortcodeButton( props: WPFormatEditProps ) {
function onSelectField( data: FieldSelection, fieldValue: string ) {
updateOrInsertField( data, fieldValue );
onClose();
sendTracksEvent( 'remotedatablocks_field_shortcode', {
action: data.action,
data_source_type: getBlockDataSourceType( data.remoteData?.blockName ),
selection_path: data.selectionPath,
} );
}

function resetField() {
function resetField( blockName?: string ): void {
updateOrInsertField( null, 'Unbound field' );
setQueryInput( null );
sendTracksEvent( 'remotedatablocks_field_shortcode', {
action: 'reset_field_shortcode',
data_source_type: getBlockDataSourceType( blockName ),
} );
}

useEffect( () => {
Expand Down Expand Up @@ -118,7 +130,9 @@ export function FieldShortcodeButton( props: WPFormatEditProps ) {
{ queryInput && (
<FieldShortcodeSelectField
blockName={ queryInput.blockName }
onSelectField={ onSelectField }
onSelectField={ ( data, fieldValue ) =>
onSelectField( { ...data, selectionPath: 'select_new_tab' }, fieldValue )
}
queryInput={ queryInput.queryInput }
fieldType="field"
/>
Expand All @@ -131,7 +145,9 @@ export function FieldShortcodeButton( props: WPFormatEditProps ) {
fieldSelection={ fieldSelection }
formatTypeSettings={ formatTypeSettings }
onClose={ onClose }
onSelectField={ onSelectField }
onSelectField={ ( data, fieldValue ) =>
onSelectField( { ...data, selectionPath: 'popover' }, fieldValue )
}
resetField={ resetField }
/>
) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export function FieldShortcodeSelectExisting( props: FieldShortcodeSelectExistin
</Heading>

<FieldSelectionFromAvailableBindings
onSelectField={ props.onSelectField }
onSelectField={ ( data, fieldValue ) =>
props.onSelectField( { ...data, selectionPath: 'select_existing_tab' }, fieldValue )
}
remoteData={ remoteData }
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ interface FieldShortcodeSelectFieldPopoverProps {
formatTypeSettings: WPFormat;
onSelectField: ( data: FieldSelection, fieldValue: string ) => void;
onClose: () => void;
resetField: () => void;
resetField: ( blockName?: string ) => void;
}

export function FieldShortcodeSelectFieldPopover( props: FieldShortcodeSelectFieldPopoverProps ) {
const popoverAnchor = useAnchor( {
editableContentElement: props.contentRef.current,
settings: props.formatTypeSettings,
} );
const { remoteData, selectedField, type } = props.fieldSelection;

return (
<Popover
Expand All @@ -43,15 +44,17 @@ export function FieldShortcodeSelectFieldPopover( props: FieldShortcodeSelectFie
</CardHeader>
<CardBody>
<FieldShortcodeSelectField
blockName={ props.fieldSelection.remoteData?.blockName ?? 'Remote Data Block' }
fieldType={ props.fieldSelection.type ?? 'field' }
onSelectField={ props.onSelectField }
queryInput={ props.fieldSelection.remoteData?.queryInput ?? {} }
selectedField={ props.fieldSelection.selectedField }
blockName={ remoteData?.blockName ?? 'Remote Data Block' }
fieldType={ type ?? 'field' }
onSelectField={ ( data, fieldValue ) =>
props.onSelectField( { ...data, action: 'update_field_shortcode' }, fieldValue )
}
queryInput={ remoteData?.queryInput ?? {} }
selectedField={ selectedField }
/>
</CardBody>
<CardFooter>
<Button onClick={ props.resetField } isDestructive>
<Button onClick={ () => props.resetField( remoteData?.blockName ) } isDestructive>
Reset field
</Button>
</CardFooter>
Expand Down
Loading

0 comments on commit ad58e6b

Please sign in to comment.