286 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			286 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/**
 | 
						|
 * Class Analytics
 | 
						|
 *
 | 
						|
 * @link      https://github.com/googleforcreators/web-stories-wp
 | 
						|
 *
 | 
						|
 * @copyright 2020 Google LLC
 | 
						|
 * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * Copyright 2020 Google LLC
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 *     https://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 */
 | 
						|
 | 
						|
declare(strict_types = 1);
 | 
						|
 | 
						|
namespace Google\Web_Stories;
 | 
						|
 | 
						|
/**
 | 
						|
 * Class Analytics
 | 
						|
 */
 | 
						|
class Analytics extends Service_Base {
 | 
						|
	/**
 | 
						|
	 * Settings instance.
 | 
						|
	 *
 | 
						|
	 * @var Settings Settings instance.
 | 
						|
	 */
 | 
						|
	private Settings $settings;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Analytics constructor.
 | 
						|
	 *
 | 
						|
	 * @since 1.12.0
 | 
						|
	 *
 | 
						|
	 * @param Settings $settings Settings instance.
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function __construct( Settings $settings ) {
 | 
						|
		$this->settings = $settings;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Initializes all hooks.
 | 
						|
	 *
 | 
						|
	 * @since 1.0.0
 | 
						|
	 */
 | 
						|
	public function register(): void {
 | 
						|
		add_action( 'web_stories_print_analytics', [ $this, 'print_analytics_tag' ] );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns the  Google Analytics tracking ID.
 | 
						|
	 *
 | 
						|
	 * @since 1.0.0
 | 
						|
	 *
 | 
						|
	 * @return string Tracking ID.
 | 
						|
	 */
 | 
						|
	public function get_tracking_id(): string {
 | 
						|
		/**
 | 
						|
		 * Tracking ID.
 | 
						|
		 *
 | 
						|
		 * @var string $tracking_id
 | 
						|
		 */
 | 
						|
		$tracking_id = $this->settings->get_setting( $this->settings::SETTING_NAME_TRACKING_ID );
 | 
						|
 | 
						|
		// For some reasons, some sites use the plugin's own tracking ID (as used in the admin)
 | 
						|
		// for their stories. Prevent accidental erroneous tracking in such a case.
 | 
						|
		if ( Tracking::TRACKING_ID === $tracking_id ) {
 | 
						|
			return '';
 | 
						|
		}
 | 
						|
 | 
						|
		return $tracking_id;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns the default analytics configuration.
 | 
						|
	 *
 | 
						|
	 * Note: variables in single quotes will be substituted by <amp-analytics>.
 | 
						|
	 *
 | 
						|
	 * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
 | 
						|
	 *
 | 
						|
	 * @see https://github.com/ampproject/amphtml/blob/main/docs/spec/amp-var-substitutions.md
 | 
						|
	 *
 | 
						|
	 * @param string $tracking_id Tracking ID.
 | 
						|
	 * @return array<string, array<string, mixed>> <amp-analytics> configuration.
 | 
						|
	 */
 | 
						|
	public function get_default_configuration( string $tracking_id ): array {
 | 
						|
		$config = [
 | 
						|
			'vars'     => [
 | 
						|
				'gtag_id' => $tracking_id,
 | 
						|
				'config'  => [
 | 
						|
					$tracking_id => [ 'groups' => 'default' ],
 | 
						|
				],
 | 
						|
			],
 | 
						|
			'triggers' => [
 | 
						|
				// Fired when a story page becomes visible.
 | 
						|
				'storyProgress'       => [
 | 
						|
					'on'      => 'story-page-visible',
 | 
						|
					'request' => 'event',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_progress',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'event_label'    => '${storyPageIndex}',
 | 
						|
						'event_value'    => '${storyProgress}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
				// Fired when the last page in the story is shown to the user.
 | 
						|
				// This can be used to measure completion rate.
 | 
						|
				'storyEnd'            => [
 | 
						|
					'on'      => 'story-last-page-visible',
 | 
						|
					'request' => 'event',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_complete',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'event_label'    => '${storyPageCount}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
				// Fired when clicking an element that opens a tooltip (<a> or <amp-twitter>).
 | 
						|
				'trackFocusState'     => [
 | 
						|
					'on'      => 'story-focus',
 | 
						|
					'tagName' => 'a',
 | 
						|
					'request' => 'click ',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_focus',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
				// Fired when clicking on a tooltip.
 | 
						|
				'trackClickThrough'   => [
 | 
						|
					'on'      => 'story-click-through',
 | 
						|
					'tagName' => 'a',
 | 
						|
					'request' => 'click ',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_click_through',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
				// Fired when opening a drawer or dialog inside a story (e.g. page attachment).
 | 
						|
				'storyOpen'           => [
 | 
						|
					'on'      => 'story-open',
 | 
						|
					'request' => 'event',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_open',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
				// Fired when closing a drawer or dialog inside a story (e.g. page attachment).
 | 
						|
				'storyClose'          => [
 | 
						|
					'on'      => 'story-close',
 | 
						|
					'request' => 'event',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_close',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
				// Fired when the user initiates an interaction to mute the audio for the current story.
 | 
						|
				'audioMuted'          => [
 | 
						|
					'on'      => 'story-audio-muted',
 | 
						|
					'request' => 'event',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_audio_muted',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
				// Fired when the user initiates an interaction to unmute the audio for the current story.
 | 
						|
				'audioUnmuted'        => [
 | 
						|
					'on'      => 'story-audio-unmuted',
 | 
						|
					'request' => 'event',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_audio_unmuted',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
				// Fired when a page attachment is opened by the user.
 | 
						|
				'pageAttachmentEnter' => [
 | 
						|
					'on'      => 'story-page-attachment-enter',
 | 
						|
					'request' => 'event',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_page_attachment_enter',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
				// Fired when a page attachment is dismissed by the user.
 | 
						|
				'pageAttachmentExit'  => [
 | 
						|
					'on'      => 'story-page-attachment-exit',
 | 
						|
					'request' => 'event',
 | 
						|
					'vars'    => [
 | 
						|
						'event_name'     => 'custom',
 | 
						|
						'event_action'   => 'story_page_attachment_exit',
 | 
						|
						'event_category' => '${title}',
 | 
						|
						'send_to'        => $tracking_id,
 | 
						|
					],
 | 
						|
				],
 | 
						|
			],
 | 
						|
		];
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Filters the Web Stories Google Analytics configuration.
 | 
						|
		 *
 | 
						|
		 * Only used when not using <amp-story-auto-analytics>, which is the default.
 | 
						|
		 *
 | 
						|
		 * @param array $config Analytics configuration.
 | 
						|
		 */
 | 
						|
		return apply_filters( 'web_stories_analytics_configuration', $config );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Prints the analytics tag for single stories.
 | 
						|
	 *
 | 
						|
	 * @since 1.0.0
 | 
						|
	 */
 | 
						|
	public function print_analytics_tag(): void {
 | 
						|
		$tracking_id = $this->get_tracking_id();
 | 
						|
 | 
						|
		if ( ! $tracking_id ) {
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		if ( $this->settings->get_setting( $this->settings::SETTING_NAME_USING_LEGACY_ANALYTICS ) ) {
 | 
						|
			$this->print_amp_analytics_tag( $tracking_id );
 | 
						|
		} else {
 | 
						|
			$this->print_amp_story_auto_analytics_tag( $tracking_id );
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Prints the legacy <amp-analytics> tag for single stories.
 | 
						|
	 *
 | 
						|
	 * @since 1.12.0
 | 
						|
	 *
 | 
						|
	 * @param string $tracking_id Tracking ID.
 | 
						|
	 */
 | 
						|
	private function print_amp_analytics_tag( string $tracking_id ): void {
 | 
						|
		?>
 | 
						|
		<amp-analytics type="gtag" data-credentials="include">
 | 
						|
			<script type="application/json">
 | 
						|
				<?php echo wp_json_encode( $this->get_default_configuration( $tracking_id ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
 | 
						|
			</script>
 | 
						|
		</amp-analytics>
 | 
						|
		<?php
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Prints the <amp-story-auto-analytics> tag for single stories.
 | 
						|
	 *
 | 
						|
	 * @since 1.12.0
 | 
						|
	 *
 | 
						|
	 * @param string $tracking_id Tracking ID.
 | 
						|
	 */
 | 
						|
	private function print_amp_story_auto_analytics_tag( string $tracking_id ): void {
 | 
						|
		?>
 | 
						|
		<amp-story-auto-analytics gtag-id="<?php echo esc_attr( $tracking_id ); ?>"></amp-story-auto-analytics>
 | 
						|
		<?php
 | 
						|
	}
 | 
						|
}
 |