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

Social: Add UTM settings and toggles #39998

Merged
merged 15 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Added toggle for UTM settings
1 change: 1 addition & 0 deletions projects/js-packages/publicize-components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export { default as PublicizePanel } from './src/components/panel';
export { default as ReviewPrompt } from './src/components/review-prompt';
export { default as PostPublishPanels } from './src/components/post-publish-panels';
export { default as ConnectionManagement } from './src/components/connection-management';
export { default as UtmToggle } from './src/components/utm-toggle';

export { default as useSocialMediaConnections } from './src/hooks/use-social-media-connections';
export { default as useSocialMediaMessage } from './src/hooks/use-social-media-message';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ToggleControl } from '@automattic/jetpack-components';
import { store as socialStore } from '@automattic/jetpack-publicize-components';
import { useSelect, useDispatch } from '@wordpress/data';
import { useCallback } from '@wordpress/element';
import React from 'react';

type ToggleProps = {
/**
* The label or content after the toggle.
*/
children: React.ReactNode;

/**
* The class name to add to the toggle.
*/
toggleClass?: string;
};

/**
* A button toggle wrapper for enabling/disabling the UTM parameters feature.
*
* @param {ToggleProps} props - Component props.
* @return {React.ReactElement} - JSX.Element
*/
const UtmToggle: React.FC< ToggleProps > = ( { toggleClass, children } ) => {
const { isEnabled, isUpdating } = useSelect( select => {
return {
isEnabled: select( socialStore ).getUtmSettings().enabled,
isUpdating: select( socialStore ).isSavingSiteSettings(),
};
}, [] );

const { updateUtmSettings } = useDispatch( socialStore );

const toggleStatus = useCallback( () => {
updateUtmSettings( { enabled: ! isEnabled } );
}, [ isEnabled, updateUtmSettings ] );

return (
<ToggleControl
className={ toggleClass }
disabled={ isUpdating }
checked={ isEnabled }
onChange={ toggleStatus }
label={ children }
/>
);
};

export default UtmToggle;
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import siteSettingActions from './jetpack-settings';
import * as shareStatus from './share-status';
import * as sigActions from './social-image-generator';
import socialNotesSettings from './social-notes-settings';
import * as utmActions from './utm-settings';

const actions = {
...shareStatus,
...siteSettingActions,
...connectionData,
...socialNotesSettings,
...sigActions,
...utmActions,
};

export default actions;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { store as coreStore } from '@wordpress/core-data';
import { UTM_ENABLED_KEY } from '../constants';
import { UtmSettingsConfig } from '../types';

/**
* Saves the UTM status.
*
* @param {Partial< UtmSettingsConfig >} data - The data to save.
*
* @return {Function} A thunk.
*/
export function updateUtmSettings( data: Partial< UtmSettingsConfig > ) {
return async function ( { registry } ) {
const { saveSite } = registry.dispatch( coreStore );

await saveSite( { [ UTM_ENABLED_KEY ]: data } );
};
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const SIG_SETTINGS_KEY = 'jetpack_social_image_generator_settings';
export const UTM_ENABLED_KEY = 'jetpack_social_utm_settings';
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import jetpackSettingSelectors from './jetpack-settings';
import * as shareStatusSelectors from './share-status';
import siteDataSelectors from './site-data';
import * as sigSelectors from './social-image-generator';
import * as utmSelectors from './utm-settings';

/**
* Returns whether the site settings are being saved.
Expand All @@ -22,6 +23,7 @@ const selectors = {
...shareStatusSelectors,
isSavingSiteSettings,
...sigSelectors,
...utmSelectors,
};

export default selectors;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { store as coreStore } from '@wordpress/core-data';
import { createRegistrySelector } from '@wordpress/data';
import { getSocialScriptData } from '../../utils';
import { UTM_ENABLED_KEY } from '../constants';
import { SocialSettingsFields, UtmSettingsConfig } from '../types';

/**
* Returns the UTM state.
*/
export const getUtmSettings = createRegistrySelector( select => () => {
const { getSite } = select( coreStore );

const settings = getSite( undefined, { _fields: UTM_ENABLED_KEY } ) as SocialSettingsFields;

// If the settings are not available in the store yet, use the default settings.
return settings?.[ UTM_ENABLED_KEY ] ?? getSocialScriptData().settings.utmSettings;
} ) as ( state: object ) => UtmSettingsConfig;
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,13 @@ export type SocialImageGeneratorConfig = {
template?: string;
};

export type UtmSettingsConfig = {
enabled: boolean;
};

export type SocialSettingsFields = {
jetpack_social_image_generator_settings: SocialImageGeneratorConfig;
jetpack_social_is_utm_enabled: boolean;
gmjuhasz marked this conversation as resolved.
Show resolved Hide resolved
};

declare global {
Expand Down
3 changes: 2 additions & 1 deletion projects/js-packages/publicize-components/src/types/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SocialImageGeneratorConfig } from '../social-store/types';
import { SocialImageGeneratorConfig, UtmSettingsConfig } from '../social-store/types';

export interface SocialUrls {
connectionsManagementPage: string;
Expand Down Expand Up @@ -33,6 +33,7 @@ export interface ApiPaths {

export type SocialSettings = {
socialImageGenerator: SocialImageGeneratorConfig;
utmSettings: UtmSettingsConfig;
};

export interface SocialScriptData {
Expand Down
4 changes: 4 additions & 0 deletions projects/packages/publicize/changelog/add-social-utm-toggle
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Added a new toggle for UTM tracking
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public static function get_social_settings() {

return array(
'socialImageGenerator' => $settings->get_image_generator_settings(),
'utmSettings' => $settings->get_utm_settings(),
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ class Settings {
'template' => Templates::DEFAULT_TEMPLATE,
);

const UTM_SETTINGS = 'utm_settings';

const DEFAULT_UTM_SETTINGS = array(
'enabled' => false,
);

/**
* Feature flags. Each item has 3 keys because of the naming conventions:
* - flag_name: The name of the feature flag for the option check.
Expand Down Expand Up @@ -129,6 +135,25 @@ public function register_settings() {
)
);

register_setting(
'jetpack_social',
self::OPTION_PREFIX . self::UTM_SETTINGS,
array(
'type' => 'boolean',
'default' => false,
'show_in_rest' => array(
'schema' => array(
'type' => 'object',
'properties' => array(
'enabled' => array(
'type' => 'boolean',
),
),
),
),
)
);

add_filter( 'rest_pre_update_setting', array( $this, 'update_settings' ), 10, 3 );
}

Expand All @@ -141,6 +166,15 @@ public function get_image_generator_settings() {
return get_option( self::OPTION_PREFIX . self::IMAGE_GENERATOR_SETTINGS, self::DEFAULT_IMAGE_GENERATOR_SETTINGS );
}

/**
* Get if the UTM params is enabled.
*
* @return array
*/
public function get_utm_settings() {
return get_option( self::OPTION_PREFIX . self::UTM_SETTINGS, self::DEFAULT_UTM_SETTINGS );
}

/**
* Get the current settings.
*
Expand All @@ -153,6 +187,7 @@ public function get_settings( $with_available = false ) {

$settings = array(
'socialImageGeneratorSettings' => $this->get_image_generator_settings(),
'utmSettings' => $this->get_utm_settings(),
Copy link
Member

Choose a reason for hiding this comment

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

I think this is no longer needed because this get_settings method is used only for the initial state. Removing this will also fix the failing PHP unit tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll remove it then I thought we still need it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed it, I'll give it another test if it works well but I'll finish the backend stuff first. If you get to test it before feel free to approve if looks good, thanks

);

// The feature cannot be enabled without Publicize.
Expand Down Expand Up @@ -222,6 +257,17 @@ public function update_settings( $updated, $name, $value ) {
if ( self::OPTION_PREFIX . self::IMAGE_GENERATOR_SETTINGS === $name ) {
return $this->update_social_image_generator_settings( $value );
}

if ( self::OPTION_PREFIX . self::UTM_SETTINGS === $name ) {
$current_utm_settings = $this->get_utm_settings();

if ( empty( $current_utm_settings ) || ! is_array( $current_utm_settings ) ) {
$current_utm_settings = self::DEFAULT_UTM_SETTINGS;
}

return update_option( self::OPTION_PREFIX . self::UTM_SETTINGS, array_replace_recursive( $current_utm_settings, $value ) );
}

return $updated;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Text } from '@automattic/jetpack-components';
import { UtmToggle } from '@automattic/jetpack-publicize-components';
import { __ } from '@wordpress/i18n';
import { FormFieldset } from '../../components/forms';
import './style.scss';

const UtmToggleSection = () => {
return (
<FormFieldset>
<UtmToggle toggleClass="jp-settings-sharing__sig-toggle">
<div>
<Text>
<strong>{ __( 'Append UTM parameters to shared URLs', 'jetpack' ) }</strong>
</Text>
{ __(
"UTM parameters are tags added to links to help track where website visitors come from, improving our understanding of how content is shared. Don't worry—it doesn't change your experience or the link destination!",
gmjuhasz marked this conversation as resolved.
Show resolved Hide resolved
'jetpack'
) }
</div>
</UtmToggle>{ ' ' }
</FormFieldset>
);
};

export default UtmToggleSection;
2 changes: 2 additions & 0 deletions projects/plugins/jetpack/_inc/client/sharing/publicize.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import './style.scss';
import { FormFieldset } from '../components/forms';
import { FEATURE_JETPACK_SOCIAL } from '../lib/plans/constants';
import SocialImageGeneratorSection from './features/social-image-generator-section';
import UtmToggleSection from './features/utm-toggle-section';

export const Publicize = withModuleSettingsFormHelpers(
class extends Component {
Expand Down Expand Up @@ -150,6 +151,7 @@ export const Publicize = withModuleSettingsFormHelpers(
{ shouldShowChildElements && hasSocialImageGenerator && (
<SocialImageGeneratorSection />
) }
{ shouldShowChildElements && <UtmToggleSection /> }
{ isActive &&
isLinked &&
useAdminUiV1 &&
Expand Down
4 changes: 4 additions & 0 deletions projects/plugins/jetpack/changelog/add-social-utm-toggle
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: enhancement

Added a new toggle for Social UTM tracking
4 changes: 4 additions & 0 deletions projects/plugins/social/changelog/add-social-utm-toggle
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Added a new toggle for UTM tracking
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import SocialImageGeneratorToggle from '../social-image-generator-toggle';
import SocialModuleToggle from '../social-module-toggle';
import SocialNotesToggle from '../social-notes-toggle';
import SupportSection from '../support-section';
import UtmToggle from '../utm-toggle';
import ConnectionScreen from './../connection-screen';
import Header from './../header';
import InfoSection from './../info-section';
Expand Down Expand Up @@ -78,6 +79,7 @@ const Admin = () => {
</AdminSectionHero>
<AdminSection>
<SocialModuleToggle />
{ isModuleEnabled && <UtmToggle /> }
{ isModuleEnabled && <SocialNotesToggle disabled={ isUpdatingJetpackSettings } /> }
{ isModuleEnabled && siteHasFeature( features.IMAGE_GENERATOR ) && (
<SocialImageGeneratorToggle disabled={ isUpdatingJetpackSettings } />
Expand Down
48 changes: 48 additions & 0 deletions projects/plugins/social/src/js/components/utm-toggle/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Text } from '@automattic/jetpack-components';
import { store as socialStore } from '@automattic/jetpack-publicize-components';
import { useSelect, useDispatch } from '@wordpress/data';
import { useCallback } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import React from 'react';
import ToggleSection from '../toggle-section';
import styles from './styles.module.scss';

type UtmToggleProps = {
/**
* If the toggle is disabled.
*/
disabled?: boolean;
};

const UtmToggle: React.FC< UtmToggleProps > = ( { disabled } ) => {
const { isEnabled, isUpdating } = useSelect( select => {
return {
isEnabled: select( socialStore ).getUtmSettings().enabled,
isUpdating: select( socialStore ).isSavingSiteSettings(),
};
}, [] );

const { updateUtmSettings } = useDispatch( socialStore );

const toggleStatus = useCallback( () => {
updateUtmSettings( { enabled: ! isEnabled } );
}, [ isEnabled, updateUtmSettings ] );

return (
<ToggleSection
title={ __( 'Append UTM parameters to shared URLs', 'jetpack-social' ) }
disabled={ isUpdating || disabled }
checked={ isEnabled }
onChange={ toggleStatus }
>
<Text className={ styles.text }>
{ __(
"UTM parameters are tags added to links to help track where website visitors come from, improving our understanding of how content is shared. Don't worry—it doesn't change your experience or the link destination!",
gmjuhasz marked this conversation as resolved.
Show resolved Hide resolved
'jetpack-social'
) }
</Text>
</ToggleSection>
);
};

export default UtmToggle;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.text {
grid-column: span 2;

a {
color: inherit;
}

@media ( min-width: 600px ) {
grid-column: 2;
}
}
Loading