Plugin Directory

Changeset 3221899


Ignore:
Timestamp:
01/14/2025 01:13:19 AM (11 months ago)
Author:
google
Message:

Update to version 1.144.0 from GitHub

Location:
google-site-kit
Files:
92 added
84 deleted
52 edited
1 copied

Legend:

Unmodified
Added
Removed
  • google-site-kit/tags/1.144.0/dist/config.php

    r3191565 r3221899  
    22/**
    33 * @package   Google\Site_Kit
    4  * @copyright 2024 Google LLC
     4 * @copyright 2025 Google LLC
    55 * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
    66 * @link      https://sitekit.withgoogle.com
     
    88
    99return array(
    10     'features' => array( 'adsPax','audienceSegmentation','conversionReporting','firstPartyMode','gm3Components','privacySandboxModule','rrmModule','signInWithGoogleModule' ),
     10    'features' => array( 'adsPax','audienceSegmentation','conversionReporting','firstPartyMode','gm3Components','privacySandboxModule','rrmModule','rrmModuleV2','signInWithGoogleModule' ),
    1111);
  • google-site-kit/tags/1.144.0/dist/manifest.php

    r3208808 r3221899  
    22/**
    33 * @package   Google\Site_Kit
    4  * @copyright 2024 Google LLC
     4 * @copyright 2025 Google LLC
    55 * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
    66 * @link      https://sitekit.withgoogle.com
     
    1919    'analytics-advanced-tracking'                          => array( "analytics-advanced-tracking-ea84b2c367b69f5c094b.js", null ),
    2020    'googlesitekit-i18n'                                   => array( "googlesitekit-i18n-33cdd2dee5d1d1f4fb34.js", null ),
    21     'googlesitekit-admin-css'                              => array( "googlesitekit-admin-css-631051a6ae95dd6157e6.min.css", null ),
     21    'googlesitekit-admin-css'                              => array( "googlesitekit-admin-css-94e047cae8f85a725061.min.css", null ),
    2222    'googlesitekit-adminbar-css'                           => array( "googlesitekit-adminbar-css-281d66e21d2b87430998.min.css", null ),
    2323    'googlesitekit-authorize-application-css'              => array( "googlesitekit-authorize-application-css-ce25e97404abc5a02921.min.css", null ),
    24     'googlesitekit-wp-dashboard-css'                       => array( "googlesitekit-wp-dashboard-css-0fc5cdb23e1da0303b0d.min.css", null ),
    25     'googlesitekit-vendor'                                 => array( "googlesitekit-vendor-6b24bb356fa23b3d09d7.js", null ),
    26     'googlesitekit-runtime'                                => array( "runtime-e5c5db16360d2c7a2c35.js", null ),
    27     'googlesitekit-activation'                             => array( "googlesitekit-activation-904456dfa45a7bf7611a.js", null ),
    28     'googlesitekit-ad-blocking-recovery'                   => array( "googlesitekit-ad-blocking-recovery-d71ee6df4e7addae69ec.js", null ),
    29     'googlesitekit-adminbar'                               => array( "googlesitekit-adminbar-9af92010e6777c6696f3.js", null ),
    30     'googlesitekit-api'                                    => array( "googlesitekit-api-19255a6b438f9ad0a040.js", null ),
    31     'googlesitekit-components'                             => array( array( "googlesitekit-components-gm2-6fe72015578197d038f1.js", null ), array( "googlesitekit-components-gm3-6af3039137f53dc8dd37.js", null ) ),
    32     'googlesitekit-data'                                   => array( "googlesitekit-data-050bcf046a0bf4e32143.js", null ),
    33     'googlesitekit-datastore-forms'                        => array( "googlesitekit-datastore-forms-52fa86100909ae62978e.js", null ),
    34     'googlesitekit-datastore-location'                     => array( "googlesitekit-datastore-location-178144613b0bcdf6a463.js", null ),
    35     'googlesitekit-datastore-site'                         => array( "googlesitekit-datastore-site-fe1cc3250299edf04507.js", null ),
    36     'googlesitekit-datastore-ui'                           => array( "googlesitekit-datastore-ui-ce7100e6b7d5cf5320f8.js", null ),
    37     'googlesitekit-datastore-user'                         => array( "googlesitekit-datastore-user-6e6dbf78ecfd97d63650.js", null ),
    38     'googlesitekit-entity-dashboard'                       => array( "googlesitekit-entity-dashboard-5b9b906ead2199337ada.js", null ),
    39     'googlesitekit-main-dashboard'                         => array( "googlesitekit-main-dashboard-06a04c1638abd60081ec.js", null ),
    40     'googlesitekit-metric-selection'                       => array( "googlesitekit-metric-selection-8622b3253697ec92bd12.js", null ),
    41     'googlesitekit-modules'                                => array( "googlesitekit-modules-b36d5dcc1fa33778aa8a.js", null ),
    42     'googlesitekit-modules-ads'                            => array( "googlesitekit-modules-ads-71257414eb8eb27b8478.js", null ),
    43     'googlesitekit-modules-adsense'                        => array( "googlesitekit-modules-adsense-9482d78b42d7ef29b823.js", null ),
    44     'googlesitekit-modules-analytics-4'                    => array( "googlesitekit-modules-analytics-4-80e726305b05bd06dacc.js", null ),
    45     'googlesitekit-modules-pagespeed-insights'             => array( "googlesitekit-modules-pagespeed-insights-06e61c09acfbcd9b87b7.js", null ),
    46     'googlesitekit-modules-reader-revenue-manager'         => array( "googlesitekit-modules-reader-revenue-manager-ba4e865f16154d2a121d.js", null ),
    47     'googlesitekit-modules-search-console'                 => array( "googlesitekit-modules-search-console-be4fffc3d4404b7d5978.js", null ),
    48     'googlesitekit-modules-sign-in-with-google'            => array( "googlesitekit-modules-sign-in-with-google-4b79763f0ae399c93438.js", null ),
    49     'googlesitekit-modules-tagmanager'                     => array( "googlesitekit-modules-tagmanager-8d556053c680ab6fed4b.js", null ),
    50     'googlesitekit-notifications'                          => array( "googlesitekit-notifications-16c629cb2b0e415158d4.js", null ),
    51     'googlesitekit-polyfills'                              => array( "googlesitekit-polyfills-fa5ebdaece9e2d991408.js", null ),
    52     'googlesitekit-settings'                               => array( "googlesitekit-settings-279994567e0f3a4dec37.js", null ),
    53     'googlesitekit-splash'                                 => array( "googlesitekit-splash-b1edbc0030571277701c.js", null ),
    54     'googlesitekit-user-input'                             => array( "googlesitekit-user-input-93f6eff03b4ad0efceb2.js", null ),
    55     'googlesitekit-widgets'                                => array( "googlesitekit-widgets-5059de819036d0cb61bd.js", null ),
    56     'googlesitekit-wp-dashboard'                           => array( "googlesitekit-wp-dashboard-f1dcc826e50bfdda1ea1.js", null ),
     24    'googlesitekit-wp-dashboard-css'                       => array( "googlesitekit-wp-dashboard-css-55d9d8bb13cf249a2389.min.css", null ),
     25    'googlesitekit-vendor'                                 => array( "googlesitekit-vendor-d03243ae7abfad569b54.js", null ),
     26    'googlesitekit-runtime'                                => array( "runtime-518bc5e73f2edcab1efb.js", null ),
     27    'googlesitekit-activation'                             => array( "googlesitekit-activation-4ea8fd8e40e650a9d08b.js", null ),
     28    'googlesitekit-ad-blocking-recovery'                   => array( "googlesitekit-ad-blocking-recovery-9740b85774e2849bad7e.js", null ),
     29    'googlesitekit-adminbar'                               => array( "googlesitekit-adminbar-c048e8e614fc061806e7.js", null ),
     30    'googlesitekit-api'                                    => array( "googlesitekit-api-8af9ef8f4fbc9c572801.js", null ),
     31    'googlesitekit-components'                             => array( array( "googlesitekit-components-gm2-1f9aa347dfbcc93399e5.js", null ), array( "googlesitekit-components-gm3-391890e40494dbc49d17.js", null ) ),
     32    'googlesitekit-data'                                   => array( "googlesitekit-data-2a3e54206716c38b1d81.js", null ),
     33    'googlesitekit-datastore-forms'                        => array( "googlesitekit-datastore-forms-c07f5742f6b5511cdc1a.js", null ),
     34    'googlesitekit-datastore-location'                     => array( "googlesitekit-datastore-location-d30857162ffddc13c031.js", null ),
     35    'googlesitekit-datastore-site'                         => array( "googlesitekit-datastore-site-591244e140dd6c4b716d.js", null ),
     36    'googlesitekit-datastore-ui'                           => array( "googlesitekit-datastore-ui-b46f8ff8d0f431237ac8.js", null ),
     37    'googlesitekit-datastore-user'                         => array( "googlesitekit-datastore-user-c76b612b20a4d1ea2781.js", null ),
     38    'googlesitekit-entity-dashboard'                       => array( "googlesitekit-entity-dashboard-db60e8148e68f48134f5.js", null ),
     39    'googlesitekit-main-dashboard'                         => array( "googlesitekit-main-dashboard-9377c3feded4b74a8419.js", null ),
     40    'googlesitekit-metric-selection'                       => array( "googlesitekit-metric-selection-2dd8d04973a21fa53f47.js", null ),
     41    'googlesitekit-modules'                                => array( "googlesitekit-modules-067dc309cdcda1a39b2d.js", null ),
     42    'googlesitekit-modules-ads'                            => array( "googlesitekit-modules-ads-9eb874e73b69cc77e625.js", null ),
     43    'googlesitekit-modules-adsense'                        => array( "googlesitekit-modules-adsense-64cc4d2004f5b4cb0798.js", null ),
     44    'googlesitekit-modules-analytics-4'                    => array( "googlesitekit-modules-analytics-4-bdacd75b9b64e64b9e46.js", null ),
     45    'googlesitekit-modules-pagespeed-insights'             => array( "googlesitekit-modules-pagespeed-insights-c788a2937d888d62b918.js", null ),
     46    'googlesitekit-modules-reader-revenue-manager'         => array( "googlesitekit-modules-reader-revenue-manager-d2e3a002b36b72b46585.js", null ),
     47    'googlesitekit-modules-search-console'                 => array( "googlesitekit-modules-search-console-126bdca347282fef9fcd.js", null ),
     48    'googlesitekit-modules-sign-in-with-google'            => array( "googlesitekit-modules-sign-in-with-google-12ef012c3e650c5cec12.js", null ),
     49    'googlesitekit-modules-tagmanager'                     => array( "googlesitekit-modules-tagmanager-016ba677d98130c56c86.js", null ),
     50    'googlesitekit-notifications'                          => array( "googlesitekit-notifications-86d5f7326de5ac167d14.js", null ),
     51    'googlesitekit-polyfills'                              => array( "googlesitekit-polyfills-90629f74b8ef58ed7ba4.js", null ),
     52    'googlesitekit-settings'                               => array( "googlesitekit-settings-43cf002db9a5f134645f.js", null ),
     53    'googlesitekit-splash'                                 => array( "googlesitekit-splash-858fc770058f52d2e4c9.js", null ),
     54    'googlesitekit-user-input'                             => array( "googlesitekit-user-input-7c5430870ff7bc5366d7.js", null ),
     55    'googlesitekit-widgets'                                => array( "googlesitekit-widgets-bb76a1c5a149ee16485a.js", null ),
     56    'googlesitekit-wp-dashboard'                           => array( "googlesitekit-wp-dashboard-7b05b49bf13c63cdb8a2.js", null ),
    5757);
  • google-site-kit/tags/1.144.0/fpm/measurement.php

    r3201134 r3221899  
    1 <?php // phpcs:disable ?>
    21<?php
     2
    33/**
    44 * FirstPartyServing redirect file
     
    88 * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
    99 *
     10 * @version   288a45a
     11 *
    1012 * NOTICE: This file has been modified from its original version in accordance with the Apache License, Version 2.0.
    11  *
    12  * PHPCS rules have been disabled at the very top of the file to allow it to be included in Site Kit's codebase mostly unmodified.
    1313 */
    1414
    1515// This file should run in isolation from any other PHP file. This means using
    16 // minimal to no external dependencies, which leads us to supressing the
     16// minimal to no external dependencies, which leads us to suppressing the
    1717// following linting rules:
    1818//
     
    2222namespace Google\FirstPartyLibrary;
    2323
     24/* Start of Site Kit modified code. */
    2425if ( isset( $_GET['healthCheck'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
    2526    echo 'ok';
    2627    exit;
    2728}
     29/* End of Site Kit modified code. */
    2830
    2931/** Core measurement.php logic. */
     
    3133{
    3234    private const TAG_ID_QUERY = '?id=';
    33     private const REDIRECTOR_ID_QUERY = '.php' . self::TAG_ID_QUERY;
    3435    private const PATH_QUERY = '&s=';
    3536    private const FPS_PATH = 'PHP_FPM_REPLACE_PATH';
    3637
    37     /** @var RequestHelper */
    38     private $helper;
     38    private RequestHelper $helper;
    3939
    4040    /**
     
    4343     * @param RequestHelper $helper
    4444     */
    45     public function __construct($helper)
     45    public function __construct(RequestHelper $helper)
    4646    {
    4747        $this->helper = $helper;
     
    5151    public function run()
    5252    {
    53         $requestString = $_SERVER['REQUEST_URI'];
    54         $documentRoot = $_SERVER['DOCUMENT_ROOT'];
    55 
    56         if (empty($documentRoot) || empty($requestString)) {
    57             $this->helper->invalidRequest(500);
    58             return "";
    59         }
    60 
    61         $redirectorFile = explode($documentRoot, __FILE__)[1];
     53        $redirectorFile = $_SERVER['SCRIPT_NAME'] ?? '';
    6254        if (empty($redirectorFile)) {
    6355            $this->helper->invalidRequest(500);
     
    6557        }
    6658
    67         $parameters = self::extractParameters($requestString);
    68         if (empty($parameters)) {
     59        $parameters = self::extractParameters();
     60
     61        $tagId = $parameters['tag_id'];
     62        $path = $parameters['path'];
     63
     64        if (empty($tagId) || empty($path)) {
    6965            $this->helper->invalidRequest(400);
    7066            return "";
    7167        }
    7268
    73         $tagId = $parameters['tag_id'];
    74         $path = $parameters['path'];
    75 
    76         if (strlen($tagId) === 0 || strlen($path) === 0) {
    77             http_response_code(400);
    78             return "";
    79         }
    80 
    8169        if (!self::isScriptRequest($path)) {
    8270            $path = self::appendRequestIP($path);
     
    8573        $fpsUrl = 'https://' . $tagId . '.fps.goog/' . self::FPS_PATH . $path;
    8674
    87         if (self::isScriptRequest($path)) {
    88             $response = $this->helper->sendRequest($fpsUrl);
    89             return str_replace(
     75        $response = $this->helper->sendRequest($fpsUrl);
     76        if (self::isScriptResponse($response['headers'])) {
     77            $response['body'] = str_replace(
    9078                '/' . self::FPS_PATH . '/',
    9179                $redirectorFile . self::TAG_ID_QUERY . $tagId . self::PATH_QUERY,
    92                 $response
     80                $response['body']
    9381            );
    94         } else {
    95             return $this->helper->sendRequest($fpsUrl);
    96         }
     82        }
     83        return $response;
    9784    }
    9885
     
    11198
    11299        $gaPath = "/g/collect";
    113         if (strpos($path, $gaPath) !== false) {
     100        if (false !== strpos($path, $gaPath)) {
    114101            return $path . '&_uip=' . $requestIP;
    115102        } else {
     
    118105    }
    119106
    120     private static function isScriptRequest($requestPath)
     107    /**
     108     * Use best effort for determining if a request path is a script request.
     109     *
     110     * @param string $requestPath
     111     * @return bool
     112     */
     113    private static function isScriptRequest(string $requestPath): bool
    121114    {
    122115        return substr($requestPath, 0, 7) === "/gtm.js"
    123         || substr($requestPath, 0, 8) === "/gtag.js"
    124         || substr($requestPath, 0, 8) === "/gtag/js";
    125     }
    126 
    127 
    128     private static function extractParameters($requestString)
    129     {
    130         $tagIdPosition = strpos($requestString, self::REDIRECTOR_ID_QUERY);
    131         if ($tagIdPosition === false) {
    132             return null;
    133         }
    134 
    135         $tagIdStart = $tagIdPosition + strlen(self::REDIRECTOR_ID_QUERY);
    136         $tagIdEnd = strpos($requestString, self::PATH_QUERY, $tagIdStart);
    137         if ($tagIdEnd === false) {
    138             return null;
    139         }
    140 
    141         $tagId = substr($requestString, $tagIdStart, $tagIdEnd - $tagIdStart);
    142         $path = substr($requestString, $tagIdEnd + strlen(self::PATH_QUERY));
     116            || substr($requestPath, 0, 8) === "/gtag.js"
     117            || substr($requestPath, 0, 8) === "/gtag/js";
     118    }
     119
     120    /**
     121     * @param string[] $headers
     122     */
     123    private static function isScriptResponse(array $headers): bool
     124    {
     125        if (empty($headers)) {
     126            return false;
     127        }
     128
     129        foreach ($headers as $header) {
     130            if (empty($header)) {
     131                continue;
     132            }
     133
     134            $normalizedHeader = strtolower(str_replace(' ', '', $header));
     135            if (strpos($normalizedHeader, 'content-type:application/javascript') === 0) {
     136                return true;
     137            }
     138        }
     139        return false;
     140    }
     141
     142    private static function extractParameters(): array
     143    {
     144        $get = $_GET;
     145        if (empty($get)) {
     146            return array(
     147                "tag_id" => '',
     148                "path" => '',
     149            );
     150        }
     151
     152        $tagId = $get['id'] ?? '';
     153        $path = $get['s'] ?? '';
     154
     155        // Validate tagId
     156        if (!preg_match('/^[A-Za-z0-9-]*$/', $tagId)) {
     157            return array(
     158                "tag_id" => '',
     159                "path" => '',
     160            );
     161        }
     162
     163        unset($get['id'], $get['s']);
     164
     165        if (!empty($get)) {
     166            $containsQueryParameters = strpos($path, '?') !== false;
     167            $paramSeparator = $containsQueryParameters ? '&' : '?';
     168            $path .= $paramSeparator . http_build_query($get, '', '&', PHP_QUERY_RFC3986);
     169        }
    143170
    144171        return array(
    145         "tag_id" => $tagId,
    146         "path" => $path,
     172            "tag_id" => $tagId,
     173            "path" => $path,
    147174        );
    148175    }
    149176}
    150177
     178// REQUEST_HELPER_START
    151179/**
    152  * Isolates network requests and other methods like exit to inject into the
    153  * Measurement class
     180 * NOTE: DO NOT edit RequestHelper directly nor remove the start and end tags.
     181 *
     182 * This class is copied over from src/RequestHelper.php. If any changes are
     183 * needed, change that file and run the command `npm run copy:RequestHelper`.
     184 */
     185/**
     186 * Isolates network requests and other methods like exit to inject into classes.
    154187 */
    155188class RequestHelper
     
    160193     * @param int $statusCode
    161194     */
    162     public function invalidRequest($statsCode)
    163     {
    164         http_response_code($statsCode);
     195    public function invalidRequest(int $statusCode): void
     196    {
     197        http_response_code($statusCode);
    165198        exit();
    166199    }
    167200
    168201    /**
     202     * Set the headers from a headers array.
     203     *
     204     * @param string[] $headers
     205     */
     206    public function setHeaders(array $headers): void
     207    {
     208        foreach ($headers as $header) {
     209            if (!empty($header)) {
     210                header($header);
     211            }
     212        }
     213    }
     214
     215    /**
    169216     * Helper method to send requests depending on the PHP environment.
    170217     *
    171218     * @param string $url
    172      */
    173     public function sendRequest($url)
     219     * @return array{
     220     *      body: string,
     221     *      headers: string[],
     222     *      statusCode: int,
     223     * }
     224     */
     225    public function sendRequest(string $url): array
    174226    {
    175227        if ($this->isCurlInstalled()) {
     
    181233    }
    182234
    183     protected function sendCurlRequest($url)
     235    /**
     236     * @param string $url
     237     * @return array{
     238     *      body: string,
     239     *      headers: string[],
     240     *      statusCode: int,
     241     * }
     242     */
     243    protected function sendCurlRequest(string $url): array
    184244    {
    185245        $ch = curl_init();
    186246        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
     247        curl_setopt($ch, CURLOPT_HEADER, true);
    187248        curl_setopt($ch, CURLOPT_URL, $url);
     249
    188250        $result = curl_exec($ch);
     251
     252        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
     253
     254        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
     255        $headersString = substr($result, 0, $headerSize);
     256        $headers = explode("\r\n", $headersString);
     257        $headers = $this->normalizeHeaders($headers);
     258
     259        $body = substr($result, $headerSize);
     260
    189261        curl_close($ch);
    190         return $result;
    191     }
    192 
    193     protected function sendFileGetContents($url)
    194     {
    195         return file_get_contents($url);
    196     }
    197 
    198     protected function isCurlInstalled()
     262
     263        return array(
     264            'body' => $body,
     265            'headers' => $headers,
     266            'statusCode' => $statusCode,
     267        );
     268    }
     269
     270    /**
     271     * @param string $url
     272     * @return array{
     273     *      body: string,
     274     *      headers: string[],
     275     *      statusCode: int,
     276     * }
     277     */
     278    protected function sendFileGetContents(string $url): array
     279    {
     280        $streamContext = stream_context_create(array(
     281            'http' => array(
     282                'method' => 'GET',
     283            )
     284        ));
     285
     286        // Calling file_get_contents will set the variable $http_response_header
     287        // within the local scope.
     288        $result = file_get_contents($url, false, $streamContext);
     289
     290        /** @var string[] $headers */
     291        $headers = $http_response_header ?? [];
     292
     293        $statusCode = 200;
     294        if (!empty($headers)) {
     295            // The first element in the headers array will be the HTTP version
     296            // and status code used, parse out the status code and remove this
     297            // value from the headers.
     298            preg_match('/HTTP\/\d\.\d\s+(\d+)/', $headers[0], $statusHeader);
     299            $statusCode = intval($statusHeader[1]) ?? 200;
     300        }
     301        $headers = $this->normalizeHeaders($headers);
     302
     303        return array(
     304            'body' => $result,
     305            'headers' => $headers,
     306            'statusCode' => $statusCode,
     307        );
     308    }
     309
     310    protected function isCurlInstalled(): bool
    199311    {
    200312        return extension_loaded('curl');
    201313    }
     314
     315    /** @param string[] $headers */
     316    protected function normalizeHeaders(array $headers): array
     317    {
     318        if (empty($headers)) {
     319            return $headers;
     320        }
     321
     322        // The first element in the headers array will be the HTTP version
     323        // and status code used, this value is not needed in the headers.
     324        array_shift($headers);
     325        return $headers;
     326    }
    202327}
     328// REQUEST_HELPER_END
    203329
    204330// Skip initial run for testing
    205331if (!defined('IS_FIRST_PARTY_MODE_TEST')) {
    206     echo (new Measurement(new RequestHelper()))->run();
     332    $requestHelper = new RequestHelper();
     333    $response = (new Measurement($requestHelper))->run();
     334
     335    $requestHelper->setHeaders($response['headers']);
     336    http_response_code($response['statusCode']);
     337    echo $response['body'];
    207338}
  • google-site-kit/tags/1.144.0/google-site-kit.php

    r3208808 r3221899  
    1212 * Plugin URI:        https://sitekit.withgoogle.com
    1313 * Description:       Site Kit is a one-stop solution for WordPress users to use everything Google has to offer to make them successful on the web.
    14  * Version:           1.142.0
     14 * Version:           1.144.0
    1515 * Requires at least: 5.2
    1616 * Requires PHP:      7.4
     
    2727
    2828// Define most essential constants.
    29 define( 'GOOGLESITEKIT_VERSION', '1.142.0' );
     29define( 'GOOGLESITEKIT_VERSION', '1.144.0' );
    3030define( 'GOOGLESITEKIT_PLUGIN_MAIN_FILE', __FILE__ );
    3131define( 'GOOGLESITEKIT_PHP_MINIMUM', '7.4.0' );
  • google-site-kit/tags/1.144.0/includes/Core/Admin/Dashboard.php

    r3034827 r3221899  
    128128     */
    129129    private function render_googlesitekit_wp_dashboard() {
     130        $active_modules                 = $this->modules->get_active_modules();
     131        $analytics_connected            = isset( $active_modules['analytics-4'] ) && $active_modules['analytics-4']->is_connected();
     132        $search_console_connected       = isset( $active_modules['search-console'] ) && $active_modules['search-console']->is_connected();
     133        $is_view_only                   = ! $this->authentication->is_authenticated();
     134        $can_view_shared_analytics      = current_user_can( Permissions::READ_SHARED_MODULE_DATA, 'analytics-4' );
     135        $can_view_shared_search_console = current_user_can( Permissions::READ_SHARED_MODULE_DATA, 'search-console' );
     136        $display_analytics_data         = ( ! $is_view_only && $analytics_connected ) || ( $is_view_only && $can_view_shared_analytics );
     137        $display_search_console_data    = ( ! $is_view_only && $search_console_connected ) || ( $is_view_only && $can_view_shared_search_console );
     138
     139        $class_names = array();
     140
     141        if ( $analytics_connected && $display_analytics_data ) {
     142            $class_names[] = 'googlesitekit-wp-dashboard-analytics_active_and_connected';
     143        }
     144
     145        if ( $search_console_connected && $display_search_console_data ) {
     146            $class_names[] = 'googlesitekit-wp-dashboard-search_console_active_and_connected';
     147        }
     148
     149        if ( ! $analytics_connected && ! $is_view_only ) {
     150            $class_names[] = 'googlesitekit-wp-dashboard-analytics-activate-cta';
     151        }
     152
     153        $class_names = implode( ' ', $class_names );
    130154
    131155        $this->render_noscript_html();
    132         $is_view_only = ! $this->authentication->is_authenticated();
    133156        ?>
    134         <div id="js-googlesitekit-wp-dashboard" data-view-only="<?php echo esc_attr( $is_view_only ); ?>" class="googlesitekit-plugin"></div>
     157        <div id="js-googlesitekit-wp-dashboard" data-view-only="<?php echo esc_attr( $is_view_only ); ?>" class="googlesitekit-plugin <?php echo esc_attr( $class_names ); ?>">
     158            <div class="googlesitekit-wp-dashboard googlesitekit-wp-dashboard-loading">
     159            <?php
     160
     161                $this->render_loading_container( 'googlesitekit-wp-dashboard__cta' );
     162            ?>
     163
     164                <div class="googlesitekit-wp-dashboard-stats">
     165                <?php
     166                if ( $display_analytics_data ) {
     167                    $this->render_loading_container( 'googlesitekit-wp-dashboard-loading__can_view_analytics' );
     168                }
     169
     170                if ( $display_search_console_data ) {
     171                    $this->render_loading_container( 'googlesitekit-wp-dashboard-loading__search_console_active_and_connected' );
     172                }
     173
     174                if ( ! $analytics_connected && ! $is_view_only ) {
     175                    $this->render_loading_container( 'googlesitekit-wp-dashboard-stats__cta' );
     176                }
     177
     178                if ( $display_analytics_data ) {
     179                    $this->render_loading_container( 'googlesitekit-unique-visitors-chart-widget' );
     180                    $this->render_loading_container( 'googlesitekit-search-console-widget' );
     181                }
     182                ?>
     183                </div>
     184            </div>
     185        </div>
    135186        <?php
    136187    }
     188
     189    /**
     190     * Render the loading container when data is not available and being fetched.
     191     *
     192     * @since 1.144.0
     193     * @param string $class_names Class names to add to the container.
     194     * @return void
     195     */
     196    private function render_loading_container( $class_names ) {
     197        ?>
     198        <div class="googlesitekit-preview-block <?php echo esc_attr( $class_names ); ?>">
     199            <div class="googlesitekit-preview-block__wrapper"></div>
     200        </div>
     201        <?php
     202    }
    137203}
  • google-site-kit/tags/1.144.0/includes/Core/Authentication/Clients/OAuth_Client.php

    r3164469 r3221899  
    571571
    572572    /**
    573      * Determines whether the authentication proxy is used.
    574      *
    575      * In order to streamline the setup and authentication flow, the plugin uses a proxy mechanism based on an external
    576      * service. This can be overridden by providing actual GCP credentials with the {@see 'googlesitekit_oauth_secret'}
    577      * filter.
    578      *
    579      * @since 1.0.0
    580      * @deprecated 1.9.0
    581      *
    582      * @return bool True if proxy authentication is used, false otherwise.
    583      */
    584     public function using_proxy() {
    585         _deprecated_function( __METHOD__, '1.9.0', Credentials::class . '::using_proxy' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    586 
    587         return $this->credentials->using_proxy();
    588     }
    589 
    590     /**
    591573     * Determines whether the current owner ID must be changed or not.
    592574     *
  • google-site-kit/tags/1.144.0/includes/Core/Key_Metrics/Key_Metrics_Settings.php

    r3208808 r3221899  
    4848    protected function get_default() {
    4949        return array(
    50             'widgetSlugs'                      => array(),
    51             'isWidgetHidden'                   => false,
    52             'includeConversionTailoredMetrics' => array(),
     50            'widgetSlugs'    => array(),
     51            'isWidgetHidden' => false,
    5352        );
    5453    }
     
    7271
    7372        $allowed_settings = array(
    74             'widgetSlugs'                      => true,
    75             'isWidgetHidden'                   => true,
    76             'includeConversionTailoredMetrics' => true,
     73            'widgetSlugs'    => true,
     74            'isWidgetHidden' => true,
    7775        );
    7876
     
    105103            }
    106104
    107             if ( isset( $settings['includeConversionTailoredMetrics'] ) ) {
    108                 $sanitized_settings['includeConversionTailoredMetrics'] = Sanitize::sanitize_string_list( $settings['includeConversionTailoredMetrics'] );
    109             }
    110 
    111105            return $sanitized_settings;
    112106        };
  • google-site-kit/tags/1.144.0/includes/Core/Key_Metrics/REST_Key_Metrics_Controller.php

    r3201134 r3221899  
    185185                )
    186186            ),
    187             new REST_Route(
    188                 'core/user/data/reset-key-metrics-selection',
    189                 array(
    190                     'methods'             => WP_REST_Server::CREATABLE,
    191                     'callback'            => function () {
    192                         $this->settings->merge( array( 'widgetSlugs' => array() ) );
    193 
    194                         return new WP_REST_Response( $this->settings->get() );
    195                     },
    196                     'permission_callback' => $has_capabilities,
    197                 )
    198             ),
    199187        );
    200188    }
  • google-site-kit/tags/1.144.0/includes/Core/Tags/First_Party_Mode/First_Party_Mode.php

    r3208808 r3221899  
    7272        $this->first_party_mode_settings = new First_Party_Mode_Settings( $options );
    7373        $this->rest_controller           = new REST_First_Party_Mode_Controller( $this, $this->first_party_mode_settings );
    74         $this->cron                      = new First_Party_Mode_Cron( array( $this, 'healthcheck' ) );
     74        $this->cron                      = new First_Party_Mode_Cron(
     75            $this->first_party_mode_settings,
     76            array( $this, 'healthcheck' )
     77        );
    7578    }
    7679
     
    184187     * @since 1.141.0
    185188     * @since 1.142.0 Relocated from REST_First_Party_Mode_Controller.
     189     * @since 1.144.0 Uses Google\FirstPartyLibrary\RequestHelper to send requests.
    186190     *
    187191     * @param string $endpoint The endpoint to check.
     
    189193     */
    190194    protected function is_endpoint_healthy( $endpoint ) {
    191         try {
    192             // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown,WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
    193             $response = file_get_contents( $endpoint );
    194         } catch ( \Exception $e ) {
     195        if ( ! defined( 'IS_FIRST_PARTY_MODE_TEST' ) ) {
     196            // TODO: This is a workaround to allow the measurement.php file to be loaded without making a
     197            // request, in order to use the RequestHelper class that it defines. We should find a better
     198            // solution in the future, but this will involve changes to the measurement.php file.
     199            define( 'IS_FIRST_PARTY_MODE_TEST', true );
     200        }
     201
     202        require_once GOOGLESITEKIT_PLUGIN_DIR_PATH . 'fpm/measurement.php';
     203
     204        $request_helper = new \Google\FirstPartyLibrary\RequestHelper();
     205
     206        $response = $request_helper->sendRequest( $endpoint );
     207
     208        if ( 200 !== $response['statusCode'] ) {
    195209            return false;
    196210        }
    197211
    198         if ( 'ok' !== $response ) {
     212        if ( 'ok' !== $response['body'] ) {
    199213            return false;
    200214        }
    201215
    202         return strpos( $http_response_header[0], '200 OK' ) !== false;
     216        return true;
    203217    }
    204218}
  • google-site-kit/tags/1.144.0/includes/Core/Tags/First_Party_Mode/First_Party_Mode_Cron.php

    r3208808 r3221899  
    3030
    3131    /**
     32     * First_Party_Mode_Settings instance.
     33     *
     34     * @var First_Party_Mode_Settings
     35     */
     36    private $first_party_mode_settings;
     37
     38    /**
    3239     * Constructor.
    3340     *
    3441     * @since 1.142.0
    3542     *
    36      * @param callable $callback Function to call on the cron action.
     43     * @param First_Party_Mode_Settings $first_party_mode_settings First_Party_Mode_Settings instance.
     44     * @param callable                  $callback                  Function to call on the cron action.
    3745     */
    38     public function __construct( callable $callback ) {
    39         $this->cron_callback = $callback;
     46    public function __construct(
     47        First_Party_Mode_Settings $first_party_mode_settings,
     48        callable $callback
     49    ) {
     50        $this->first_party_mode_settings = $first_party_mode_settings;
     51        $this->cron_callback             = $callback;
    4052    }
    4153
     
    5567     */
    5668    public function maybe_schedule_cron() {
    57         if ( ! wp_next_scheduled( self::CRON_ACTION ) && ! wp_installing() ) {
     69        $settings    = $this->first_party_mode_settings->get();
     70        $fpm_enabled = $settings['isEnabled'];
     71
     72        if (
     73            $fpm_enabled &&
     74            ! wp_next_scheduled( self::CRON_ACTION ) &&
     75            ! wp_installing()
     76        ) {
    5877            wp_schedule_event( time(), 'hourly', self::CRON_ACTION );
    5978        }
  • google-site-kit/tags/1.144.0/includes/Core/User/User.php

    r3141863 r3221899  
    1414
    1515/**
    16  * Class for handling audience settings rest routes.
     16 * Class for handling user settings rest routes.
    1717 *
    1818 * @since 1.134.0
     
    3131
    3232    /**
     33     * Conversion_Reporting instance.
     34     *
     35     * @since 1.144.0
     36     * @var Conversion_Reporting
     37     */
     38    private $conversion_reporting;
     39
     40    /**
    3341     * Constructor.
    3442     *
     
    3947    public function __construct( User_Options $user_options ) {
    4048        $this->audience_segmentation = new Audience_Segmentation( $user_options );
     49        $this->conversion_reporting  = new Conversion_Reporting( $user_options );
    4150    }
    4251
     
    4857    public function register() {
    4958        $this->audience_segmentation->register();
     59        $this->conversion_reporting->register();
    5060    }
    5161}
  • google-site-kit/tags/1.144.0/includes/Core/User_Input/User_Input.php

    r3022626 r3221899  
    6868     */
    6969    private static $questions = array(
    70         'purpose'       => array(
     70        'purpose'                 => array(
    7171            'scope' => 'site',
    7272        ),
    73         'postFrequency' => array(
     73        'postFrequency'           => array(
    7474            'scope' => 'user',
    7575        ),
    76         'goals'         => array(
     76        'goals'                   => array(
    7777            'scope' => 'user',
     78        ),
     79        'includeConversionEvents' => array(
     80            'scope' => 'site',
    7881        ),
    7982    );
     
    200203            }
    201204        }
     205
     206        // Conversion events may be empty during setup if no events have been detected.
     207        // Since this setting does not affect whether user input is considered "set up",
     208        // we are excluding it from this check. It relates to user input initially being
     209        // set up with detected events or events added later.
     210        unset( $settings['includeConversionEvents'] );
    202211
    203212        foreach ( $settings as $setting ) {
  • google-site-kit/tags/1.144.0/includes/Modules/AdSense.php

    r3201134 r3221899  
    749749            'name'        => _x( 'AdSense', 'Service name', 'google-site-kit' ),
    750750            'description' => __( 'Earn money by placing ads on your website. It’s free and easy.', 'google-site-kit' ),
    751             'order'       => 2,
    752751            'homepage'    => add_query_arg( $idenfifier_args, 'https://adsense.google.com/start' ),
    753752        );
  • google-site-kit/tags/1.144.0/includes/Modules/Ads.php

    r3208808 r3221899  
    143143                    array(
    144144                        // When updating, mirror the fixed version for google-pax-sdk in package.json.
    145                         'src'          => 'https://www.gstatic.com/pax/1.0.12/pax_integrator.js',
     145                        'src'          => 'https://www.gstatic.com/pax/1.1.0/pax_integrator.js',
    146146                        'execution'    => 'async',
    147147                        'dependencies' => array(
     
    209209            'name'        => _x( 'Ads', 'Service name', 'google-site-kit' ),
    210210            'description' => Feature_Flags::enabled( 'adsPax' ) ? __( 'Grow sales, leads or awareness for your business by advertising with Google Ads', 'google-site-kit' ) : __( 'Track conversions for your existing Google Ads campaigns', 'google-site-kit' ),
    211             'order'       => 1,
    212211            'homepage'    => __( 'https://google.com/ads', 'google-site-kit' ),
    213212        );
  • google-site-kit/tags/1.144.0/includes/Modules/Ads/Web_Tag.php

    r3075250 r3221899  
    1414use Google\Site_Kit\Core\Tags\GTag;
    1515use Google\Site_Kit\Core\Tags\Tag_With_Linker_Interface;
     16use Google\Site_Kit\Core\Tags\Tag_With_Linker_Trait;
    1617use Google\Site_Kit\Core\Util\Method_Proxy_Trait;
    1718
     
    2627
    2728    use Method_Proxy_Trait;
    28 
    29     /**
    30      * Sets the current home domain.
    31      *
    32      * @since 1.125.0
    33      *
    34      * @param string $domain Domain name.
    35      */
    36     public function set_home_domain( $domain ) {
    37         $this->home_domain = $domain;
    38     }
     29    use Tag_With_Linker_Trait;
    3930
    4031    /**
  • google-site-kit/tags/1.144.0/includes/Modules/Analytics_4.php

    r3208808 r3221899  
    9393use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_Cron;
    9494use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_Events_Sync;
     95use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_New_Badge_Events_Sync;
    9596use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_Provider;
    9697use Google\Site_Kit\Modules\Analytics_4\Reset_Audiences;
    9798use stdClass;
    9899use WP_Error;
     100use WP_Post;
    99101
    100102/**
     
    706708        }
    707709
    708         if ( Feature_Flags::enabled( 'conversionReporting' ) ) {
    709             $datapoints['POST:clear-conversion-reporting-new-events']  = array(
    710                 'service' => '',
    711             );
    712             $datapoints['POST:clear-conversion-reporting-lost-events'] = array(
    713                 'service' => '',
    714             );
    715         }
    716 
    717710        return $datapoints;
    718711    }
     
    14591452                $custom_dimension->setParameterName( $custom_dimension_data['parameterName'] );
    14601453                $custom_dimension->setDisplayName( $custom_dimension_data['displayName'] );
    1461                 $custom_dimension->setDescription( $custom_dimension_data['description'] );
    14621454                $custom_dimension->setScope( $custom_dimension_data['scope'] );
    1463                 $custom_dimension->setDisallowAdsPersonalization( $custom_dimension_data['disallowAdsPersonalization'] );
     1455
     1456                if ( isset( $custom_dimension_data['description'] ) ) {
     1457                    $custom_dimension->setDescription( $custom_dimension_data['description'] );
     1458                }
     1459
     1460                if ( isset( $custom_dimension_data['disallowAdsPersonalization'] ) ) {
     1461                    $custom_dimension->setDisallowAdsPersonalization( $custom_dimension_data['disallowAdsPersonalization'] );
     1462                }
    14641463
    14651464                $analyticsadmin = $this->get_service( 'analyticsadmin' );
     
    16841683                return function () use ( $data ) {
    16851684                    return $this->transients->set( 'googlesitekit_inline_tag_id_mismatch', $data['hasMismatchedTag'] );
    1686                 };
    1687             case 'POST:clear-conversion-reporting-new-events':
    1688                 return function () {
    1689                     return $this->transients->delete( Conversion_Reporting_Events_Sync::DETECTED_EVENTS_TRANSIENT );
    1690                 };
    1691             case 'POST:clear-conversion-reporting-lost-events':
    1692                 return function () {
    1693                     return $this->transients->delete( Conversion_Reporting_Events_Sync::LOST_EVENTS_TRANSIENT );
    16941685                };
    16951686        }
     
    18321823            'name'        => _x( 'Analytics', 'Service name', 'google-site-kit' ),
    18331824            'description' => __( 'Get a deeper understanding of your customers. Google Analytics gives you the free tools you need to analyze data for your business in one place.', 'google-site-kit' ),
    1834             'order'       => 3,
    18351825            'homepage'    => __( 'https://analytics.google.com/analytics/web', 'google-site-kit' ),
    18361826        );
     
    20402030        $post = get_queried_object();
    20412031
     2032        if ( ! $post instanceof WP_Post ) {
     2033            return $data;
     2034        }
     2035
    20422036        if ( in_array( 'googlesitekit_post_type', $settings['availableCustomDimensions'], true ) ) {
    20432037            $data['googlesitekit_post_type'] = $post->post_type;
     
    26142608        }
    26152609
    2616         $detected_events                           = $this->transients->get( Conversion_Reporting_Events_Sync::DETECTED_EVENTS_TRANSIENT );
    2617         $lost_events                               = $this->transients->get( Conversion_Reporting_Events_Sync::LOST_EVENTS_TRANSIENT );
    2618         $modules_data['analytics-4']['newEvents']  = is_array( $detected_events ) ? $detected_events : array();
    2619         $modules_data['analytics-4']['lostEvents'] = is_array( $lost_events ) ? $lost_events : array();
     2610        $detected_events  = $this->transients->get( Conversion_Reporting_Events_Sync::DETECTED_EVENTS_TRANSIENT );
     2611        $lost_events      = $this->transients->get( Conversion_Reporting_Events_Sync::LOST_EVENTS_TRANSIENT );
     2612        $new_events_badge = $this->transients->get( Conversion_Reporting_New_Badge_Events_Sync::NEW_EVENTS_BADGE_TRANSIENT );
     2613
     2614        $modules_data['analytics-4']['newEvents']      = is_array( $detected_events ) ? $detected_events : array();
     2615        $modules_data['analytics-4']['lostEvents']     = is_array( $lost_events ) ? $lost_events : array();
     2616        $modules_data['analytics-4']['newBadgeEvents'] = is_array( $new_events_badge ) ? $new_events_badge['events'] : array();
    26202617
    26212618        return $modules_data;
  • google-site-kit/tags/1.144.0/includes/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Events_Sync.php

    r3181737 r3221899  
    1414use Google\Site_Kit\Modules\Analytics_4\Settings;
    1515use Google\Site_Kit\Core\Storage\Transients;
    16 use Google\Site_Kit\Context;
    1716
    1817/**
     
    5857
    5958    /**
     59     * Conversion_Reporting_New_Badge_Events_Sync instance.
     60     *
     61     * @var Conversion_Reporting_New_Badge_Events_Sync
     62     */
     63    private $new_badge_events_sync;
     64
     65    /**
    6066     * Transients instance.
    6167     *
     
    7076     * @since 1.135.0
    7177     * @since 1.139.0 Added $context param to constructor.
     78     * @since 1.144.0 Added $transients and $new_badge_events_sync params to constructor, and removed $context.
    7279     *
    73      * @param Context     $context   Plugin context.
    74      * @param Settings    $settings  Settings module settings instance.
    75      * @param Analytics_4 $analytics Analytics 4 module instance.
     80     * @param Settings                                   $settings              Settings module settings instance.
     81     * @param Transients                                 $transients            Transients instance.
     82     * @param Analytics_4                                $analytics             Analytics 4 module instance.
     83     * @param Conversion_Reporting_New_Badge_Events_Sync $new_badge_events_sync Conversion_Reporting_New_Badge_Events_Sync instance.
    7684     */
    7785    public function __construct(
    78         Context $context,
    7986        Settings $settings,
    80         Analytics_4 $analytics
     87        Transients $transients,
     88        Analytics_4 $analytics,
     89        Conversion_Reporting_New_Badge_Events_Sync $new_badge_events_sync
    8190    ) {
    82         $this->settings   = $settings;
    83         $this->analytics  = $analytics;
    84         $this->transients = new Transients( $context );
     91        $this->settings              = $settings;
     92        $this->transients            = $transients;
     93        $this->analytics             = $analytics;
     94        $this->new_badge_events_sync = $new_badge_events_sync;
    8595    }
    8696
     
    118128            $detected_events[] = $row['dimensionValues'][0]['value'];
    119129        }
     130        $settings_partial = array( 'detectedEvents' => $detected_events );
    120131
     132        $this->maybe_update_new_and_lost_events(
     133            $detected_events,
     134            $saved_detected_events,
     135            $settings_partial
     136        );
     137
     138        $this->settings->merge( $settings_partial );
     139    }
     140
     141    /**
     142     * Saves new and lost events transients.
     143     *
     144     * @since 1.144.0
     145     *
     146     * @param array $detected_events       Currently detected events array.
     147     * @param array $saved_detected_events Previously saved detected events array.
     148     * @param array $settings_partial      Analaytics settings partial.
     149     */
     150    protected function maybe_update_new_and_lost_events( $detected_events, $saved_detected_events, &$settings_partial ) {
    121151        $new_events  = array_diff( $detected_events, $saved_detected_events );
    122152        $lost_events = array_diff( $saved_detected_events, $detected_events );
     
    124154        if ( ! empty( $new_events ) ) {
    125155            $this->transients->set( self::DETECTED_EVENTS_TRANSIENT, array_values( $new_events ) );
     156            $this->new_badge_events_sync->sync_new_badge_events( $new_events );
     157            $settings_partial['newConversionEventsLastUpdateAt'] = time();
    126158        }
    127159
    128160        if ( ! empty( $lost_events ) ) {
    129161            $this->transients->set( self::LOST_EVENTS_TRANSIENT, array_values( $lost_events ) );
     162            $settings_partial['lostConversionEventsLastUpdateAt'] = time();
    130163        }
    131164
     
    133166            $this->transients->set( self::DETECTED_EVENTS_TRANSIENT, $detected_events );
    134167        }
    135 
    136         $this->settings->merge( array( 'detectedEvents' => $detected_events ) );
    137168    }
    138169
  • google-site-kit/tags/1.144.0/includes/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Provider.php

    r3181737 r3221899  
    1212
    1313use Google\Site_Kit\Context;
     14use Google\Site_Kit\Core\Storage\Transients;
    1415use Google\Site_Kit\Core\Storage\User_Options;
    1516use Google\Site_Kit\Modules\Analytics_4;
     
    7374        $this->analytics    = $analytics;
    7475
    75         $this->events_sync = new Conversion_Reporting_Events_Sync( $context, $settings, $this->analytics );
    76         $this->cron        = new Conversion_Reporting_Cron( fn() => $this->cron_callback() );
     76        $transients            = new Transients( $context );
     77        $new_badge_events_sync = new Conversion_Reporting_New_Badge_Events_Sync( $transients );
     78        $this->events_sync     = new Conversion_Reporting_Events_Sync(
     79            $settings,
     80            $transients,
     81            $this->analytics,
     82            $new_badge_events_sync
     83        );
     84        $this->cron            = new Conversion_Reporting_Cron( fn() => $this->cron_callback() );
    7785    }
    7886
  • google-site-kit/tags/1.144.0/includes/Modules/Analytics_4/Settings.php

    r3181737 r3221899  
    7575            'audienceSegmentationSetupCompletedBy',
    7676            'detectedEvents',
     77            'newConversionEventsLastUpdateAt',
     78            'lostConversionEventsLastUpdateAt',
    7779        );
    7880    }
     
    111113            'audienceSegmentationSetupCompletedBy' => null,
    112114            'detectedEvents'                       => array(),
     115            'newConversionEventsLastUpdateAt'      => 0,
     116            'lostConversionEventsLastUpdateAt'     => 0,
    113117        );
    114118    }
     
    214218                    }
    215219                }
     220
     221                if ( isset( $option['newConversionEventsLastUpdateAt'] ) ) {
     222                    if ( ! is_int( $option['newConversionEventsLastUpdateAt'] ) ) {
     223                        $option['newConversionEventsLastUpdateAt'] = 0;
     224                    }
     225                }
     226
     227                if ( isset( $option['lostConversionEventsLastUpdateAt'] ) ) {
     228                    if ( ! is_int( $option['lostConversionEventsLastUpdateAt'] ) ) {
     229                        $option['lostConversionEventsLastUpdateAt'] = 0;
     230                    }
     231                }
    216232            }
    217233
  • google-site-kit/tags/1.144.0/includes/Modules/PageSpeed_Insights.php

    r3118692 r3221899  
    181181            'name'        => _x( 'PageSpeed Insights', 'Service name', 'google-site-kit' ),
    182182            'description' => __( 'Google PageSpeed Insights gives you metrics about performance, accessibility, SEO and PWA', 'google-site-kit' ),
    183             'order'       => 4,
    184183            'homepage'    => __( 'https://pagespeed.web.dev', 'google-site-kit' ),
    185184        );
  • google-site-kit/tags/1.144.0/includes/Modules/Reader_Revenue_Manager.php

    r3201134 r3221899  
    333333            'name'        => _x( 'Reader Revenue Manager', 'Service name', 'google-site-kit' ),
    334334            'description' => __( 'Reader Revenue Manager helps publishers grow, retain, and engage their audiences, creating new revenue opportunities', 'google-site-kit' ),
    335             'order'       => 5,
    336335            'homepage'    => 'https://publishercenter.google.com',
    337336        );
  • google-site-kit/tags/1.144.0/includes/Modules/Sign_In_With_Google.php

    r3208808 r3221899  
    127127        add_action( 'admin_action_' . self::ACTION_DISCONNECT, fn () => $this->handle_disconnect_user() );
    128128
    129         add_action( 'login_form', $this->get_method_proxy( 'render_signin_button' ) );
    130 
    131129        add_action( 'show_user_profile', $this->get_method_proxy( 'render_disconnect_profile' ) ); // This action shows the disconnect section on the users own profile page.
    132130        add_action( 'edit_user_profile', $this->get_method_proxy( 'render_disconnect_profile' ) ); // This action shows the disconnect section on other users profile page to allow admins to disconnect others.
    133131
    134         add_action( 'woocommerce_login_form_start', $this->get_method_proxy( 'render_signin_button' ) );
     132        // (Potentially) render the Sign in with Google script tags/buttons.
     133        add_action( 'wp_footer', $this->get_method_proxy( 'render_signinwithgoogle' ) );
     134        // Output the Sign in with Google JS on the WordPress login page.
     135        add_action( 'login_footer', $this->get_method_proxy( 'render_signinwithgoogle' ) );
    135136
    136137        // Delete client ID stored from previous module connection on module reconnection.
     
    227228            'name'        => _x( 'Sign in with Google', 'Service name', 'google-site-kit' ),
    228229            'description' => __( 'Improve user engagement, trust and data privacy, while creating a simple, secure and personalized experience for your visitors', 'google-site-kit' ),
    229             'order'       => 10,
    230230            'homepage'    => __( 'https://developers.google.com/identity/gsi/web/guides/overview', 'google-site-kit' ),
    231231        );
     
    289289
    290290    /**
    291      * Renders the sign in button.
     291     * Renders the Sign in with Google JS script tags, One-tap code, and
     292     * buttons.
    292293     *
    293294     * @since 1.139.0
    294      */
    295     private function render_signin_button() {
     295     * @since 1.144.0 Renamed to `render_signinwithgoogle` and conditionally
     296     *                rendered the code to replace buttons.
     297     */
     298    private function render_signinwithgoogle() {
    296299        global $wp;
     300        $is_wp_login           = is_login();
    297301        $is_woo_commerce_login = 'my-account' === $wp->request;
    298302
    299303        $settings = $this->get_settings()->get();
     304
     305        // If there's no client ID available, don't render the button.
    300306        if ( ! $settings['clientID'] ) {
     307            return;
     308        }
     309
     310        // If this is not the WordPress or WooCommerce login page, check to
     311        // see if "One-tap enabled on all pages" is set first. If it isnt:
     312        // don't render the Sign in with Google JS.
     313        if ( ! $is_wp_login && ! $is_woo_commerce_login && ! $settings['oneTapOnAllPages'] ) {
    301314            return;
    302315        }
     
    317330            'shape' => $settings['shape'],
    318331        );
     332
     333        // Whether buttons will be rendered/transformed on this page.
     334        $render_buttons = $is_wp_login || $is_woo_commerce_login;
    319335
    320336        // Render the Sign in with Google button and related inline styles.
     
    329345        ?>
    330346( () => {
    331     const parent = document.createElement( 'div' );
    332 <?php if ( $is_woo_commerce_login ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    333     document.getElementsByClassName( 'login' )[0]?.insertBefore( parent, document.getElementsByClassName( 'woocommerce-form-row' )[0] );
    334         <?php else : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    335     document.getElementById( 'login' ).insertBefore( parent, document.getElementById( 'loginform' ) );
     347    <?php if ( $render_buttons ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     348        const parent = document.createElement( 'div' );
     349
     350        <?php if ( $is_wp_login ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     351            document.getElementById( 'login' ).insertBefore( parent, document.getElementById( 'loginform' ) );
    336352        <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     353
     354        <?php if ( $is_woo_commerce_login ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     355            document.getElementsByClassName( 'login' )[0]?.insertBefore( parent, document.getElementsByClassName( 'woocommerce-form-row' )[0] );
     356        <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     357    <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    337358
    338359    async function handleCredentialResponse( response ) {
     
    342363                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    343364                body: new URLSearchParams( response )
    344             });
     365            } );
    345366            if ( res.ok && res.redirected ) {
    346367                location.assign( res.url );
     
    354375        client_id: '<?php echo esc_js( $settings['clientID'] ); ?>',
    355376        callback: handleCredentialResponse,
     377        library_name: 'Site-Kit',
    356378    } );
    357379
    358     google.accounts.id.renderButton( parent, <?php echo wp_json_encode( $btn_args ); ?> );
    359 
    360 <?php if ( $settings['oneTapEnabled'] ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    361     google.accounts.id.prompt();
    362         <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    363 
    364 <?php if ( ! empty( $redirect_to ) ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    365     const expires = new Date();
    366     expires.setTime( expires.getTime() + 1000 * 60 * 5 );
    367     document.cookie = "<?php echo esc_js( Authenticator::COOKIE_REDIRECT_TO ); ?>=<?php echo esc_js( $redirect_to ); ?>;expires="  + expires.toUTCString() + ";path=<?php echo esc_js( Authenticator::get_cookie_path() ); ?>";
    368         <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     380    <?php if ( $render_buttons ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     381        google.accounts.id.renderButton( parent, <?php echo wp_json_encode( $btn_args ); ?> );
     382    <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     383
     384    <?php if ( $settings['oneTapEnabled'] && ( $is_wp_login || ! is_user_logged_in() ) ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     385        google.accounts.id.prompt();
     386    <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     387
     388    <?php if ( $render_buttons && ! empty( $redirect_to ) ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     389        const expires = new Date();
     390        expires.setTime( expires.getTime() + 1000 * 60 * 5 );
     391        document.cookie = "<?php echo esc_js( Authenticator::COOKIE_REDIRECT_TO ); ?>=<?php echo esc_js( $redirect_to ); ?>;expires="  + expires.toUTCString() + ";path=<?php echo esc_js( Authenticator::get_cookie_path() ); ?>";
     392    <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    369393} )();
    370394        <?php
    371395        BC_Functions::wp_print_inline_script_tag( ob_get_clean() );
    372         printf( "\n<!-- %s -->\n", esc_html__( 'End Sign in with Google button added by Site Kit', 'google-site-kit' ) );
     396        print( "\n<!-- End Sign in with Google button added by Site Kit -->\n" );
    373397    }
    374398
  • google-site-kit/tags/1.144.0/includes/Modules/Sign_In_With_Google/Settings.php

    r3191565 r3221899  
    8787    protected function get_default() {
    8888        return array(
    89             'clientID'      => '',
    90             'text'          => self::TEXT_SIGN_IN_WITH_GOOGLE['value'],
    91             'theme'         => self::THEME_LIGHT['value'],
    92             'shape'         => self::SHAPE_RECTANGULAR['value'],
    93             'oneTapEnabled' => false,
     89            'clientID'         => '',
     90            'text'             => self::TEXT_SIGN_IN_WITH_GOOGLE['value'],
     91            'theme'            => self::THEME_LIGHT['value'],
     92            'shape'            => self::SHAPE_RECTANGULAR['value'],
     93            'oneTapEnabled'    => false,
     94            'oneTapOnAllPages' => false,
    9495        );
    9596    }
     
    152153            }
    153154
     155            if ( isset( $option['oneTapOnAllPages'] ) ) {
     156                $option['oneTapOnAllPages'] = (bool) $option['oneTapOnAllPages'];
     157            }
     158
    154159            return $option;
    155160        };
  • google-site-kit/tags/1.144.0/includes/Modules/Tag_Manager.php

    r3208808 r3221899  
    467467            'name'        => _x( 'Tag Manager', 'Service name', 'google-site-kit' ),
    468468            'description' => __( 'Tag Manager creates an easy to manage way to create tags on your site without updating code', 'google-site-kit' ),
    469             'order'       => 6,
    470469            'homepage'    => __( 'https://tagmanager.google.com/', 'google-site-kit' ),
    471470        );
  • google-site-kit/tags/1.144.0/includes/vendor/composer/autoload_classmap.php

    r3208808 r3221899  
    196196    'Google\\Site_Kit\\Core\\User\\Audience_Segmentation' => $baseDir . '/Core/User/Audience_Segmentation.php',
    197197    'Google\\Site_Kit\\Core\\User\\Audience_Settings' => $baseDir . '/Core/User/Audience_Settings.php',
     198    'Google\\Site_Kit\\Core\\User\\Conversion_Reporting' => $baseDir . '/Core/User/Conversion_Reporting.php',
     199    'Google\\Site_Kit\\Core\\User\\Conversion_Reporting_Settings' => $baseDir . '/Core/User/Conversion_Reporting_Settings.php',
    198200    'Google\\Site_Kit\\Core\\User\\REST_Audience_Settings_Controller' => $baseDir . '/Core/User/REST_Audience_Settings_Controller.php',
     201    'Google\\Site_Kit\\Core\\User\\REST_Conversion_Reporting_Controller' => $baseDir . '/Core/User/REST_Conversion_Reporting_Controller.php',
    199202    'Google\\Site_Kit\\Core\\User\\User' => $baseDir . '/Core/User/User.php',
    200203    'Google\\Site_Kit\\Core\\User_Input\\REST_User_Input_Controller' => $baseDir . '/Core/User_Input/REST_User_Input_Controller.php',
     
    269272    'Google\\Site_Kit\\Modules\\Analytics_4\\Conversion_Reporting\\Conversion_Reporting_Cron' => $baseDir . '/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Cron.php',
    270273    'Google\\Site_Kit\\Modules\\Analytics_4\\Conversion_Reporting\\Conversion_Reporting_Events_Sync' => $baseDir . '/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Events_Sync.php',
     274    'Google\\Site_Kit\\Modules\\Analytics_4\\Conversion_Reporting\\Conversion_Reporting_New_Badge_Events_Sync' => $baseDir . '/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_New_Badge_Events_Sync.php',
    271275    'Google\\Site_Kit\\Modules\\Analytics_4\\Conversion_Reporting\\Conversion_Reporting_Provider' => $baseDir . '/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Provider.php',
    272276    'Google\\Site_Kit\\Modules\\Analytics_4\\Custom_Dimensions_Data_Available' => $baseDir . '/Modules/Analytics_4/Custom_Dimensions_Data_Available.php',
  • google-site-kit/tags/1.144.0/readme.txt

    r3208808 r3221899  
    55Tested up to:      6.7
    66Requires PHP:      7.4
    7 Stable tag:        1.142.0
     7Stable tag:        1.144.0
    88License:           Apache License 2.0
    99License URI:       https://www.apache.org/licenses/LICENSE-2.0
     
    110110== Changelog ==
    111111
    112 = 1.142.0 =
     112= 1.144.0 =
    113113
    114114**Added**
    115115
    116 * Add Analytics events to Sign in with Google. See [#9747](https://github.com/google/site-kit-wp/issues/9747).
     116* Add `library_name` parameter to Sign in with Google button. See [#9924](https://github.com/google/site-kit-wp/issues/9924).
     117* Add incremental ESLint rule to avoid defining `scenario.label` on stories. See [#9865](https://github.com/google/site-kit-wp/issues/9865).
     118* Add option to enable "One-tap" sign-in across site when using Sign in with Google. See [#9861](https://github.com/google/site-kit-wp/issues/9861).
    117119
    118120**Enhanced**
    119121
    120 * Fix the "improve your measurement" section's layout in mobile viewports. See [#9830](https://github.com/google/site-kit-wp/issues/9830).
    121 * Update the default value of the First-party mode `isEnabled` setting to `false`. See [#9828](https://github.com/google/site-kit-wp/issues/9828).
    122 * Add periodic server requirement health checks for first-party mode. See [#9768](https://github.com/google/site-kit-wp/issues/9768).
    123 * Always display the "Anyone can register" WordPress setting in Sign in with Google settings. See [#9735](https://github.com/google/site-kit-wp/issues/9735).
    124 * Update learn more link in Sign in with Google module settings. See [#9734](https://github.com/google/site-kit-wp/issues/9734).
    125 * Update copy in Sign in with Google "Connect more services" UI. See [#9733](https://github.com/google/site-kit-wp/issues/9733).
    126 * Update Sign in with Google setup success notification UI. See [#9724](https://github.com/google/site-kit-wp/issues/9724).
    127 * Automatically dismiss the First-Party Mode setup banner notification when the toggle is enabled from the settings screen, preventing redundant notifications. See [#9698](https://github.com/google/site-kit-wp/issues/9698).
    128 * Add a selector to detect changes and an action to reset First-party mode settings, integrated with Analytics and Ads rollback and validation processes. See [#9688](https://github.com/google/site-kit-wp/issues/9688).
    129 * Add FPFE health check and script access statuses to Site Kit’s Site Health section, displaying whether these checks are enabled or disabled. See [#9668](https://github.com/google/site-kit-wp/issues/9668).
    130 * Add First-Party Mode status to Site Kit’s Site Health section, displaying whether the feature is enabled or not when either the Analytics or Ads modules are connected and the `firstPartyMode` feature flag is active. See [#9667](https://github.com/google/site-kit-wp/issues/9667).
    131 * Add support for gtag to load in first-party mode when enabled. See [#9664](https://github.com/google/site-kit-wp/issues/9664).
    132 * Display the First-party mode enabled status in the Ads settings view. See [#9659](https://github.com/google/site-kit-wp/issues/9659).
    133 * Display the First-party mode enabled status in the Analytics settings view. See [#9658](https://github.com/google/site-kit-wp/issues/9658).
    134 * Integrate the First-party mode toggle into the Ads module’s settings form, allowing users to enable or disable First-party mode. See [#9655](https://github.com/google/site-kit-wp/issues/9655).
    135 * Integrate the First-party mode toggle into the Analytics module’s settings form, allowing users to enable or disable First-party mode. See [#9654](https://github.com/google/site-kit-wp/issues/9654).
    136 * Group measurement toggles together on the settings screen in the Ads and Analytics module edit sections. See [#9651](https://github.com/google/site-kit-wp/issues/9651).
    137 * Add a "Beta" badge to the First-party mode toggle. See [#9650](https://github.com/google/site-kit-wp/issues/9650).
    138 * Implement the First-party mode toggle as a component which is presented in Storybook. See [#9649](https://github.com/google/site-kit-wp/issues/9649).
    139 * Add first-party mode setup success notification. See [#9648](https://github.com/google/site-kit-wp/issues/9648).
    140 * Add the First-party mode setup banner to let users know about the feature and enable it from the dashboard. See [#9647](https://github.com/google/site-kit-wp/issues/9647).
    141 * Update spacing between CTA actions for consistency. See [#9600](https://github.com/google/site-kit-wp/issues/9600).
    142 * Add notification banner when event data has been missing for ninety days. See [#9578](https://github.com/google/site-kit-wp/issues/9578).
    143 * Improve notifications rendering performance. See [#9488](https://github.com/google/site-kit-wp/issues/9488).
    144 * Add full size selection panel on the new screen. See [#9375](https://github.com/google/site-kit-wp/issues/9375).
    145 * Update Analytics Conversion Report notifications to be more context-aware. See [#9373](https://github.com/google/site-kit-wp/issues/9373).
    146 * Ensure Analytics Conversion Reports notification appears for users who set up Key Metrics manually. See [#9372](https://github.com/google/site-kit-wp/issues/9372).
    147 * Ensure that the setup flow for a module is automatically continued when clicking the "Redo setup" CTA on the "Site Kit can’t access necessary data" unsatisfied scopes notification. See [#9261](https://github.com/google/site-kit-wp/issues/9261).
    148 * Extend Consent Mode conditions logic. See [#9147](https://github.com/google/site-kit-wp/issues/9147).
     122* Add the `rrmModuleV2` feature flag, this will be used for phase two of the Reader Revenue Manager module's development. See [#9948](https://github.com/google/site-kit-wp/issues/9948).
     123* Update FPM health check to use the approach from the measurement script. See [#9916](https://github.com/google/site-kit-wp/issues/9916).
     124* Improve Analytics Conversion Reporting new/lost events callouts experience for each Site Kit user. See [#9897](https://github.com/google/site-kit-wp/issues/9897).
     125* Update subtle notification padding for consistency with the Figma design. See [#9860](https://github.com/google/site-kit-wp/issues/9860).
     126* Add a loading spinner to the "Enable First-party mode" CTA button on the setup banner to indicate progress during the setup process. See [#9856](https://github.com/google/site-kit-wp/issues/9856).
     127* Only run the periodic server requirement health checks for First-party mode when the mode is enabled. See [#9842](https://github.com/google/site-kit-wp/issues/9842).
     128* Update Partner Ads Experience with knowledge of supported conversion events. See [#9816](https://github.com/google/site-kit-wp/issues/9816).
     129* Improve logic for persisting badges in the Key Metrics selection panel. See [#9798](https://github.com/google/site-kit-wp/issues/9798).
     130* Add the Suggested group to the key metrics selection panel. See [#9797](https://github.com/google/site-kit-wp/issues/9797).
     131* Add a warning notification on the dashboard to alert users when First-party mode is disabled due to failed server requirement checks. See [#9767](https://github.com/google/site-kit-wp/issues/9767).
     132* Update to the latest version of the First-party mode proxy script. See [#9710](https://github.com/google/site-kit-wp/issues/9710).
     133* Add "Learn more" links for First-party mode. See [#9699](https://github.com/google/site-kit-wp/issues/9699).
     134* Introduce GA4 tracking events for the First-party mode feature. See [#9669](https://github.com/google/site-kit-wp/issues/9669).
     135* Add loading state with placeholder elements to Site Kit's WP dashboard widget. See [#9570](https://github.com/google/site-kit-wp/issues/9570).
     136* Fix issues with Audience Creation Notice when browser viewport is very short. See [#9562](https://github.com/google/site-kit-wp/issues/9562).
     137* Improve accuracy of periodic network connection check. See [#9485](https://github.com/google/site-kit-wp/issues/9485).
     138* Add badge to new Analytics Conversion Reporting widget tiles and groups. See [#9386](https://github.com/google/site-kit-wp/issues/9386).
     139* Update the Setup Error Banner notification to use the new Notifications API. See [#9283](https://github.com/google/site-kit-wp/issues/9283).
     140* Move settings edit dependency loading state to module stores. See [#8730](https://github.com/google/site-kit-wp/issues/8730).
     141* Improve the "See full details" link in AdSense settings, linking to the list of sites for the account where possible. See [#8076](https://github.com/google/site-kit-wp/issues/8076).
     142* Ensure that cities and countries with unset values don't show up in the "Top cities driving traffic" and "Top countries driving traffic" Key Metric tiles. See [#7884](https://github.com/google/site-kit-wp/issues/7884).
     143
     144**Changed**
     145
     146* Remove the deprecated `OAuth_Client::using_proxy` method and its associated tests. See [#8366](https://github.com/google/site-kit-wp/issues/8366).
    149147
    150148**Fixed**
    151149
    152 * Update the Sign in with Google module to suggest using the previous client ID when re-connecting the module. See [#9744](https://github.com/google/site-kit-wp/issues/9744).
    153 * Ensure Sign in with Google translations are consistent. See [#9738](https://github.com/google/site-kit-wp/issues/9738).
    154 * Add Sign in with Google live preview in settings. See [#9718](https://github.com/google/site-kit-wp/issues/9718).
    155 * Update layout of Top Content widget in smaller viewports to use a tab per metric column. See [#7563](https://github.com/google/site-kit-wp/issues/7563).
     150* Ensure measurement tracking requests succeed when both the Analytics and Ads modules are connected and First-party mode is enabled. See [#9901](https://github.com/google/site-kit-wp/issues/9901).
     151* Improve sort order in module list. See [#9877](https://github.com/google/site-kit-wp/issues/9877).
     152* Ensure "Enhanced Measurement" setting is not activated when disabled during Analytics setup. See [#9827](https://github.com/google/site-kit-wp/issues/9827).
     153* Fix a glitch where setup CTA banners would momentarily appear again when dismissing their admin settings tooltip. See [#9791](https://github.com/google/site-kit-wp/issues/9791).
     154* Fix iPad 10 Safari inconsistencies. See [#9776](https://github.com/google/site-kit-wp/issues/9776).
     155* Fix potential for PHP warning related to accessing a property `post_type` on null. See [#9762](https://github.com/google/site-kit-wp/issues/9762).
     156* Ensure Site Kit's Google chart on the WordPress dashboard widget correctly adapts to viewport width changes. See [#9756](https://github.com/google/site-kit-wp/issues/9756).
     157* Fix the deprecation error in the Ads module related to the creation of a dynamic property in the `Web_Tag` class. See [#9531](https://github.com/google/site-kit-wp/issues/9531).
     158* Prevent unnecessary requests on dashboard. See [#9178](https://github.com/google/site-kit-wp/issues/9178).
     159* Prevent PHP warnings when creating custom dimensions. See [#7801](https://github.com/google/site-kit-wp/issues/7801).
    156160
    157161[See changelog for all versions](https://raw.githubusercontent.com/google/site-kit-wp/main/changelog.txt).
  • google-site-kit/trunk/dist/config.php

    r3191565 r3221899  
    22/**
    33 * @package   Google\Site_Kit
    4  * @copyright 2024 Google LLC
     4 * @copyright 2025 Google LLC
    55 * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
    66 * @link      https://sitekit.withgoogle.com
     
    88
    99return array(
    10     'features' => array( 'adsPax','audienceSegmentation','conversionReporting','firstPartyMode','gm3Components','privacySandboxModule','rrmModule','signInWithGoogleModule' ),
     10    'features' => array( 'adsPax','audienceSegmentation','conversionReporting','firstPartyMode','gm3Components','privacySandboxModule','rrmModule','rrmModuleV2','signInWithGoogleModule' ),
    1111);
  • google-site-kit/trunk/dist/manifest.php

    r3208808 r3221899  
    22/**
    33 * @package   Google\Site_Kit
    4  * @copyright 2024 Google LLC
     4 * @copyright 2025 Google LLC
    55 * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
    66 * @link      https://sitekit.withgoogle.com
     
    1919    'analytics-advanced-tracking'                          => array( "analytics-advanced-tracking-ea84b2c367b69f5c094b.js", null ),
    2020    'googlesitekit-i18n'                                   => array( "googlesitekit-i18n-33cdd2dee5d1d1f4fb34.js", null ),
    21     'googlesitekit-admin-css'                              => array( "googlesitekit-admin-css-631051a6ae95dd6157e6.min.css", null ),
     21    'googlesitekit-admin-css'                              => array( "googlesitekit-admin-css-94e047cae8f85a725061.min.css", null ),
    2222    'googlesitekit-adminbar-css'                           => array( "googlesitekit-adminbar-css-281d66e21d2b87430998.min.css", null ),
    2323    'googlesitekit-authorize-application-css'              => array( "googlesitekit-authorize-application-css-ce25e97404abc5a02921.min.css", null ),
    24     'googlesitekit-wp-dashboard-css'                       => array( "googlesitekit-wp-dashboard-css-0fc5cdb23e1da0303b0d.min.css", null ),
    25     'googlesitekit-vendor'                                 => array( "googlesitekit-vendor-6b24bb356fa23b3d09d7.js", null ),
    26     'googlesitekit-runtime'                                => array( "runtime-e5c5db16360d2c7a2c35.js", null ),
    27     'googlesitekit-activation'                             => array( "googlesitekit-activation-904456dfa45a7bf7611a.js", null ),
    28     'googlesitekit-ad-blocking-recovery'                   => array( "googlesitekit-ad-blocking-recovery-d71ee6df4e7addae69ec.js", null ),
    29     'googlesitekit-adminbar'                               => array( "googlesitekit-adminbar-9af92010e6777c6696f3.js", null ),
    30     'googlesitekit-api'                                    => array( "googlesitekit-api-19255a6b438f9ad0a040.js", null ),
    31     'googlesitekit-components'                             => array( array( "googlesitekit-components-gm2-6fe72015578197d038f1.js", null ), array( "googlesitekit-components-gm3-6af3039137f53dc8dd37.js", null ) ),
    32     'googlesitekit-data'                                   => array( "googlesitekit-data-050bcf046a0bf4e32143.js", null ),
    33     'googlesitekit-datastore-forms'                        => array( "googlesitekit-datastore-forms-52fa86100909ae62978e.js", null ),
    34     'googlesitekit-datastore-location'                     => array( "googlesitekit-datastore-location-178144613b0bcdf6a463.js", null ),
    35     'googlesitekit-datastore-site'                         => array( "googlesitekit-datastore-site-fe1cc3250299edf04507.js", null ),
    36     'googlesitekit-datastore-ui'                           => array( "googlesitekit-datastore-ui-ce7100e6b7d5cf5320f8.js", null ),
    37     'googlesitekit-datastore-user'                         => array( "googlesitekit-datastore-user-6e6dbf78ecfd97d63650.js", null ),
    38     'googlesitekit-entity-dashboard'                       => array( "googlesitekit-entity-dashboard-5b9b906ead2199337ada.js", null ),
    39     'googlesitekit-main-dashboard'                         => array( "googlesitekit-main-dashboard-06a04c1638abd60081ec.js", null ),
    40     'googlesitekit-metric-selection'                       => array( "googlesitekit-metric-selection-8622b3253697ec92bd12.js", null ),
    41     'googlesitekit-modules'                                => array( "googlesitekit-modules-b36d5dcc1fa33778aa8a.js", null ),
    42     'googlesitekit-modules-ads'                            => array( "googlesitekit-modules-ads-71257414eb8eb27b8478.js", null ),
    43     'googlesitekit-modules-adsense'                        => array( "googlesitekit-modules-adsense-9482d78b42d7ef29b823.js", null ),
    44     'googlesitekit-modules-analytics-4'                    => array( "googlesitekit-modules-analytics-4-80e726305b05bd06dacc.js", null ),
    45     'googlesitekit-modules-pagespeed-insights'             => array( "googlesitekit-modules-pagespeed-insights-06e61c09acfbcd9b87b7.js", null ),
    46     'googlesitekit-modules-reader-revenue-manager'         => array( "googlesitekit-modules-reader-revenue-manager-ba4e865f16154d2a121d.js", null ),
    47     'googlesitekit-modules-search-console'                 => array( "googlesitekit-modules-search-console-be4fffc3d4404b7d5978.js", null ),
    48     'googlesitekit-modules-sign-in-with-google'            => array( "googlesitekit-modules-sign-in-with-google-4b79763f0ae399c93438.js", null ),
    49     'googlesitekit-modules-tagmanager'                     => array( "googlesitekit-modules-tagmanager-8d556053c680ab6fed4b.js", null ),
    50     'googlesitekit-notifications'                          => array( "googlesitekit-notifications-16c629cb2b0e415158d4.js", null ),
    51     'googlesitekit-polyfills'                              => array( "googlesitekit-polyfills-fa5ebdaece9e2d991408.js", null ),
    52     'googlesitekit-settings'                               => array( "googlesitekit-settings-279994567e0f3a4dec37.js", null ),
    53     'googlesitekit-splash'                                 => array( "googlesitekit-splash-b1edbc0030571277701c.js", null ),
    54     'googlesitekit-user-input'                             => array( "googlesitekit-user-input-93f6eff03b4ad0efceb2.js", null ),
    55     'googlesitekit-widgets'                                => array( "googlesitekit-widgets-5059de819036d0cb61bd.js", null ),
    56     'googlesitekit-wp-dashboard'                           => array( "googlesitekit-wp-dashboard-f1dcc826e50bfdda1ea1.js", null ),
     24    'googlesitekit-wp-dashboard-css'                       => array( "googlesitekit-wp-dashboard-css-55d9d8bb13cf249a2389.min.css", null ),
     25    'googlesitekit-vendor'                                 => array( "googlesitekit-vendor-d03243ae7abfad569b54.js", null ),
     26    'googlesitekit-runtime'                                => array( "runtime-518bc5e73f2edcab1efb.js", null ),
     27    'googlesitekit-activation'                             => array( "googlesitekit-activation-4ea8fd8e40e650a9d08b.js", null ),
     28    'googlesitekit-ad-blocking-recovery'                   => array( "googlesitekit-ad-blocking-recovery-9740b85774e2849bad7e.js", null ),
     29    'googlesitekit-adminbar'                               => array( "googlesitekit-adminbar-c048e8e614fc061806e7.js", null ),
     30    'googlesitekit-api'                                    => array( "googlesitekit-api-8af9ef8f4fbc9c572801.js", null ),
     31    'googlesitekit-components'                             => array( array( "googlesitekit-components-gm2-1f9aa347dfbcc93399e5.js", null ), array( "googlesitekit-components-gm3-391890e40494dbc49d17.js", null ) ),
     32    'googlesitekit-data'                                   => array( "googlesitekit-data-2a3e54206716c38b1d81.js", null ),
     33    'googlesitekit-datastore-forms'                        => array( "googlesitekit-datastore-forms-c07f5742f6b5511cdc1a.js", null ),
     34    'googlesitekit-datastore-location'                     => array( "googlesitekit-datastore-location-d30857162ffddc13c031.js", null ),
     35    'googlesitekit-datastore-site'                         => array( "googlesitekit-datastore-site-591244e140dd6c4b716d.js", null ),
     36    'googlesitekit-datastore-ui'                           => array( "googlesitekit-datastore-ui-b46f8ff8d0f431237ac8.js", null ),
     37    'googlesitekit-datastore-user'                         => array( "googlesitekit-datastore-user-c76b612b20a4d1ea2781.js", null ),
     38    'googlesitekit-entity-dashboard'                       => array( "googlesitekit-entity-dashboard-db60e8148e68f48134f5.js", null ),
     39    'googlesitekit-main-dashboard'                         => array( "googlesitekit-main-dashboard-9377c3feded4b74a8419.js", null ),
     40    'googlesitekit-metric-selection'                       => array( "googlesitekit-metric-selection-2dd8d04973a21fa53f47.js", null ),
     41    'googlesitekit-modules'                                => array( "googlesitekit-modules-067dc309cdcda1a39b2d.js", null ),
     42    'googlesitekit-modules-ads'                            => array( "googlesitekit-modules-ads-9eb874e73b69cc77e625.js", null ),
     43    'googlesitekit-modules-adsense'                        => array( "googlesitekit-modules-adsense-64cc4d2004f5b4cb0798.js", null ),
     44    'googlesitekit-modules-analytics-4'                    => array( "googlesitekit-modules-analytics-4-bdacd75b9b64e64b9e46.js", null ),
     45    'googlesitekit-modules-pagespeed-insights'             => array( "googlesitekit-modules-pagespeed-insights-c788a2937d888d62b918.js", null ),
     46    'googlesitekit-modules-reader-revenue-manager'         => array( "googlesitekit-modules-reader-revenue-manager-d2e3a002b36b72b46585.js", null ),
     47    'googlesitekit-modules-search-console'                 => array( "googlesitekit-modules-search-console-126bdca347282fef9fcd.js", null ),
     48    'googlesitekit-modules-sign-in-with-google'            => array( "googlesitekit-modules-sign-in-with-google-12ef012c3e650c5cec12.js", null ),
     49    'googlesitekit-modules-tagmanager'                     => array( "googlesitekit-modules-tagmanager-016ba677d98130c56c86.js", null ),
     50    'googlesitekit-notifications'                          => array( "googlesitekit-notifications-86d5f7326de5ac167d14.js", null ),
     51    'googlesitekit-polyfills'                              => array( "googlesitekit-polyfills-90629f74b8ef58ed7ba4.js", null ),
     52    'googlesitekit-settings'                               => array( "googlesitekit-settings-43cf002db9a5f134645f.js", null ),
     53    'googlesitekit-splash'                                 => array( "googlesitekit-splash-858fc770058f52d2e4c9.js", null ),
     54    'googlesitekit-user-input'                             => array( "googlesitekit-user-input-7c5430870ff7bc5366d7.js", null ),
     55    'googlesitekit-widgets'                                => array( "googlesitekit-widgets-bb76a1c5a149ee16485a.js", null ),
     56    'googlesitekit-wp-dashboard'                           => array( "googlesitekit-wp-dashboard-7b05b49bf13c63cdb8a2.js", null ),
    5757);
  • google-site-kit/trunk/fpm/measurement.php

    r3201134 r3221899  
    1 <?php // phpcs:disable ?>
    21<?php
     2
    33/**
    44 * FirstPartyServing redirect file
     
    88 * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
    99 *
     10 * @version   288a45a
     11 *
    1012 * NOTICE: This file has been modified from its original version in accordance with the Apache License, Version 2.0.
    11  *
    12  * PHPCS rules have been disabled at the very top of the file to allow it to be included in Site Kit's codebase mostly unmodified.
    1313 */
    1414
    1515// This file should run in isolation from any other PHP file. This means using
    16 // minimal to no external dependencies, which leads us to supressing the
     16// minimal to no external dependencies, which leads us to suppressing the
    1717// following linting rules:
    1818//
     
    2222namespace Google\FirstPartyLibrary;
    2323
     24/* Start of Site Kit modified code. */
    2425if ( isset( $_GET['healthCheck'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
    2526    echo 'ok';
    2627    exit;
    2728}
     29/* End of Site Kit modified code. */
    2830
    2931/** Core measurement.php logic. */
     
    3133{
    3234    private const TAG_ID_QUERY = '?id=';
    33     private const REDIRECTOR_ID_QUERY = '.php' . self::TAG_ID_QUERY;
    3435    private const PATH_QUERY = '&s=';
    3536    private const FPS_PATH = 'PHP_FPM_REPLACE_PATH';
    3637
    37     /** @var RequestHelper */
    38     private $helper;
     38    private RequestHelper $helper;
    3939
    4040    /**
     
    4343     * @param RequestHelper $helper
    4444     */
    45     public function __construct($helper)
     45    public function __construct(RequestHelper $helper)
    4646    {
    4747        $this->helper = $helper;
     
    5151    public function run()
    5252    {
    53         $requestString = $_SERVER['REQUEST_URI'];
    54         $documentRoot = $_SERVER['DOCUMENT_ROOT'];
    55 
    56         if (empty($documentRoot) || empty($requestString)) {
    57             $this->helper->invalidRequest(500);
    58             return "";
    59         }
    60 
    61         $redirectorFile = explode($documentRoot, __FILE__)[1];
     53        $redirectorFile = $_SERVER['SCRIPT_NAME'] ?? '';
    6254        if (empty($redirectorFile)) {
    6355            $this->helper->invalidRequest(500);
     
    6557        }
    6658
    67         $parameters = self::extractParameters($requestString);
    68         if (empty($parameters)) {
     59        $parameters = self::extractParameters();
     60
     61        $tagId = $parameters['tag_id'];
     62        $path = $parameters['path'];
     63
     64        if (empty($tagId) || empty($path)) {
    6965            $this->helper->invalidRequest(400);
    7066            return "";
    7167        }
    7268
    73         $tagId = $parameters['tag_id'];
    74         $path = $parameters['path'];
    75 
    76         if (strlen($tagId) === 0 || strlen($path) === 0) {
    77             http_response_code(400);
    78             return "";
    79         }
    80 
    8169        if (!self::isScriptRequest($path)) {
    8270            $path = self::appendRequestIP($path);
     
    8573        $fpsUrl = 'https://' . $tagId . '.fps.goog/' . self::FPS_PATH . $path;
    8674
    87         if (self::isScriptRequest($path)) {
    88             $response = $this->helper->sendRequest($fpsUrl);
    89             return str_replace(
     75        $response = $this->helper->sendRequest($fpsUrl);
     76        if (self::isScriptResponse($response['headers'])) {
     77            $response['body'] = str_replace(
    9078                '/' . self::FPS_PATH . '/',
    9179                $redirectorFile . self::TAG_ID_QUERY . $tagId . self::PATH_QUERY,
    92                 $response
     80                $response['body']
    9381            );
    94         } else {
    95             return $this->helper->sendRequest($fpsUrl);
    96         }
     82        }
     83        return $response;
    9784    }
    9885
     
    11198
    11299        $gaPath = "/g/collect";
    113         if (strpos($path, $gaPath) !== false) {
     100        if (false !== strpos($path, $gaPath)) {
    114101            return $path . '&_uip=' . $requestIP;
    115102        } else {
     
    118105    }
    119106
    120     private static function isScriptRequest($requestPath)
     107    /**
     108     * Use best effort for determining if a request path is a script request.
     109     *
     110     * @param string $requestPath
     111     * @return bool
     112     */
     113    private static function isScriptRequest(string $requestPath): bool
    121114    {
    122115        return substr($requestPath, 0, 7) === "/gtm.js"
    123         || substr($requestPath, 0, 8) === "/gtag.js"
    124         || substr($requestPath, 0, 8) === "/gtag/js";
    125     }
    126 
    127 
    128     private static function extractParameters($requestString)
    129     {
    130         $tagIdPosition = strpos($requestString, self::REDIRECTOR_ID_QUERY);
    131         if ($tagIdPosition === false) {
    132             return null;
    133         }
    134 
    135         $tagIdStart = $tagIdPosition + strlen(self::REDIRECTOR_ID_QUERY);
    136         $tagIdEnd = strpos($requestString, self::PATH_QUERY, $tagIdStart);
    137         if ($tagIdEnd === false) {
    138             return null;
    139         }
    140 
    141         $tagId = substr($requestString, $tagIdStart, $tagIdEnd - $tagIdStart);
    142         $path = substr($requestString, $tagIdEnd + strlen(self::PATH_QUERY));
     116            || substr($requestPath, 0, 8) === "/gtag.js"
     117            || substr($requestPath, 0, 8) === "/gtag/js";
     118    }
     119
     120    /**
     121     * @param string[] $headers
     122     */
     123    private static function isScriptResponse(array $headers): bool
     124    {
     125        if (empty($headers)) {
     126            return false;
     127        }
     128
     129        foreach ($headers as $header) {
     130            if (empty($header)) {
     131                continue;
     132            }
     133
     134            $normalizedHeader = strtolower(str_replace(' ', '', $header));
     135            if (strpos($normalizedHeader, 'content-type:application/javascript') === 0) {
     136                return true;
     137            }
     138        }
     139        return false;
     140    }
     141
     142    private static function extractParameters(): array
     143    {
     144        $get = $_GET;
     145        if (empty($get)) {
     146            return array(
     147                "tag_id" => '',
     148                "path" => '',
     149            );
     150        }
     151
     152        $tagId = $get['id'] ?? '';
     153        $path = $get['s'] ?? '';
     154
     155        // Validate tagId
     156        if (!preg_match('/^[A-Za-z0-9-]*$/', $tagId)) {
     157            return array(
     158                "tag_id" => '',
     159                "path" => '',
     160            );
     161        }
     162
     163        unset($get['id'], $get['s']);
     164
     165        if (!empty($get)) {
     166            $containsQueryParameters = strpos($path, '?') !== false;
     167            $paramSeparator = $containsQueryParameters ? '&' : '?';
     168            $path .= $paramSeparator . http_build_query($get, '', '&', PHP_QUERY_RFC3986);
     169        }
    143170
    144171        return array(
    145         "tag_id" => $tagId,
    146         "path" => $path,
     172            "tag_id" => $tagId,
     173            "path" => $path,
    147174        );
    148175    }
    149176}
    150177
     178// REQUEST_HELPER_START
    151179/**
    152  * Isolates network requests and other methods like exit to inject into the
    153  * Measurement class
     180 * NOTE: DO NOT edit RequestHelper directly nor remove the start and end tags.
     181 *
     182 * This class is copied over from src/RequestHelper.php. If any changes are
     183 * needed, change that file and run the command `npm run copy:RequestHelper`.
     184 */
     185/**
     186 * Isolates network requests and other methods like exit to inject into classes.
    154187 */
    155188class RequestHelper
     
    160193     * @param int $statusCode
    161194     */
    162     public function invalidRequest($statsCode)
    163     {
    164         http_response_code($statsCode);
     195    public function invalidRequest(int $statusCode): void
     196    {
     197        http_response_code($statusCode);
    165198        exit();
    166199    }
    167200
    168201    /**
     202     * Set the headers from a headers array.
     203     *
     204     * @param string[] $headers
     205     */
     206    public function setHeaders(array $headers): void
     207    {
     208        foreach ($headers as $header) {
     209            if (!empty($header)) {
     210                header($header);
     211            }
     212        }
     213    }
     214
     215    /**
    169216     * Helper method to send requests depending on the PHP environment.
    170217     *
    171218     * @param string $url
    172      */
    173     public function sendRequest($url)
     219     * @return array{
     220     *      body: string,
     221     *      headers: string[],
     222     *      statusCode: int,
     223     * }
     224     */
     225    public function sendRequest(string $url): array
    174226    {
    175227        if ($this->isCurlInstalled()) {
     
    181233    }
    182234
    183     protected function sendCurlRequest($url)
     235    /**
     236     * @param string $url
     237     * @return array{
     238     *      body: string,
     239     *      headers: string[],
     240     *      statusCode: int,
     241     * }
     242     */
     243    protected function sendCurlRequest(string $url): array
    184244    {
    185245        $ch = curl_init();
    186246        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
     247        curl_setopt($ch, CURLOPT_HEADER, true);
    187248        curl_setopt($ch, CURLOPT_URL, $url);
     249
    188250        $result = curl_exec($ch);
     251
     252        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
     253
     254        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
     255        $headersString = substr($result, 0, $headerSize);
     256        $headers = explode("\r\n", $headersString);
     257        $headers = $this->normalizeHeaders($headers);
     258
     259        $body = substr($result, $headerSize);
     260
    189261        curl_close($ch);
    190         return $result;
    191     }
    192 
    193     protected function sendFileGetContents($url)
    194     {
    195         return file_get_contents($url);
    196     }
    197 
    198     protected function isCurlInstalled()
     262
     263        return array(
     264            'body' => $body,
     265            'headers' => $headers,
     266            'statusCode' => $statusCode,
     267        );
     268    }
     269
     270    /**
     271     * @param string $url
     272     * @return array{
     273     *      body: string,
     274     *      headers: string[],
     275     *      statusCode: int,
     276     * }
     277     */
     278    protected function sendFileGetContents(string $url): array
     279    {
     280        $streamContext = stream_context_create(array(
     281            'http' => array(
     282                'method' => 'GET',
     283            )
     284        ));
     285
     286        // Calling file_get_contents will set the variable $http_response_header
     287        // within the local scope.
     288        $result = file_get_contents($url, false, $streamContext);
     289
     290        /** @var string[] $headers */
     291        $headers = $http_response_header ?? [];
     292
     293        $statusCode = 200;
     294        if (!empty($headers)) {
     295            // The first element in the headers array will be the HTTP version
     296            // and status code used, parse out the status code and remove this
     297            // value from the headers.
     298            preg_match('/HTTP\/\d\.\d\s+(\d+)/', $headers[0], $statusHeader);
     299            $statusCode = intval($statusHeader[1]) ?? 200;
     300        }
     301        $headers = $this->normalizeHeaders($headers);
     302
     303        return array(
     304            'body' => $result,
     305            'headers' => $headers,
     306            'statusCode' => $statusCode,
     307        );
     308    }
     309
     310    protected function isCurlInstalled(): bool
    199311    {
    200312        return extension_loaded('curl');
    201313    }
     314
     315    /** @param string[] $headers */
     316    protected function normalizeHeaders(array $headers): array
     317    {
     318        if (empty($headers)) {
     319            return $headers;
     320        }
     321
     322        // The first element in the headers array will be the HTTP version
     323        // and status code used, this value is not needed in the headers.
     324        array_shift($headers);
     325        return $headers;
     326    }
    202327}
     328// REQUEST_HELPER_END
    203329
    204330// Skip initial run for testing
    205331if (!defined('IS_FIRST_PARTY_MODE_TEST')) {
    206     echo (new Measurement(new RequestHelper()))->run();
     332    $requestHelper = new RequestHelper();
     333    $response = (new Measurement($requestHelper))->run();
     334
     335    $requestHelper->setHeaders($response['headers']);
     336    http_response_code($response['statusCode']);
     337    echo $response['body'];
    207338}
  • google-site-kit/trunk/google-site-kit.php

    r3208808 r3221899  
    1212 * Plugin URI:        https://sitekit.withgoogle.com
    1313 * Description:       Site Kit is a one-stop solution for WordPress users to use everything Google has to offer to make them successful on the web.
    14  * Version:           1.142.0
     14 * Version:           1.144.0
    1515 * Requires at least: 5.2
    1616 * Requires PHP:      7.4
     
    2727
    2828// Define most essential constants.
    29 define( 'GOOGLESITEKIT_VERSION', '1.142.0' );
     29define( 'GOOGLESITEKIT_VERSION', '1.144.0' );
    3030define( 'GOOGLESITEKIT_PLUGIN_MAIN_FILE', __FILE__ );
    3131define( 'GOOGLESITEKIT_PHP_MINIMUM', '7.4.0' );
  • google-site-kit/trunk/includes/Core/Admin/Dashboard.php

    r3034827 r3221899  
    128128     */
    129129    private function render_googlesitekit_wp_dashboard() {
     130        $active_modules                 = $this->modules->get_active_modules();
     131        $analytics_connected            = isset( $active_modules['analytics-4'] ) && $active_modules['analytics-4']->is_connected();
     132        $search_console_connected       = isset( $active_modules['search-console'] ) && $active_modules['search-console']->is_connected();
     133        $is_view_only                   = ! $this->authentication->is_authenticated();
     134        $can_view_shared_analytics      = current_user_can( Permissions::READ_SHARED_MODULE_DATA, 'analytics-4' );
     135        $can_view_shared_search_console = current_user_can( Permissions::READ_SHARED_MODULE_DATA, 'search-console' );
     136        $display_analytics_data         = ( ! $is_view_only && $analytics_connected ) || ( $is_view_only && $can_view_shared_analytics );
     137        $display_search_console_data    = ( ! $is_view_only && $search_console_connected ) || ( $is_view_only && $can_view_shared_search_console );
     138
     139        $class_names = array();
     140
     141        if ( $analytics_connected && $display_analytics_data ) {
     142            $class_names[] = 'googlesitekit-wp-dashboard-analytics_active_and_connected';
     143        }
     144
     145        if ( $search_console_connected && $display_search_console_data ) {
     146            $class_names[] = 'googlesitekit-wp-dashboard-search_console_active_and_connected';
     147        }
     148
     149        if ( ! $analytics_connected && ! $is_view_only ) {
     150            $class_names[] = 'googlesitekit-wp-dashboard-analytics-activate-cta';
     151        }
     152
     153        $class_names = implode( ' ', $class_names );
    130154
    131155        $this->render_noscript_html();
    132         $is_view_only = ! $this->authentication->is_authenticated();
    133156        ?>
    134         <div id="js-googlesitekit-wp-dashboard" data-view-only="<?php echo esc_attr( $is_view_only ); ?>" class="googlesitekit-plugin"></div>
     157        <div id="js-googlesitekit-wp-dashboard" data-view-only="<?php echo esc_attr( $is_view_only ); ?>" class="googlesitekit-plugin <?php echo esc_attr( $class_names ); ?>">
     158            <div class="googlesitekit-wp-dashboard googlesitekit-wp-dashboard-loading">
     159            <?php
     160
     161                $this->render_loading_container( 'googlesitekit-wp-dashboard__cta' );
     162            ?>
     163
     164                <div class="googlesitekit-wp-dashboard-stats">
     165                <?php
     166                if ( $display_analytics_data ) {
     167                    $this->render_loading_container( 'googlesitekit-wp-dashboard-loading__can_view_analytics' );
     168                }
     169
     170                if ( $display_search_console_data ) {
     171                    $this->render_loading_container( 'googlesitekit-wp-dashboard-loading__search_console_active_and_connected' );
     172                }
     173
     174                if ( ! $analytics_connected && ! $is_view_only ) {
     175                    $this->render_loading_container( 'googlesitekit-wp-dashboard-stats__cta' );
     176                }
     177
     178                if ( $display_analytics_data ) {
     179                    $this->render_loading_container( 'googlesitekit-unique-visitors-chart-widget' );
     180                    $this->render_loading_container( 'googlesitekit-search-console-widget' );
     181                }
     182                ?>
     183                </div>
     184            </div>
     185        </div>
    135186        <?php
    136187    }
     188
     189    /**
     190     * Render the loading container when data is not available and being fetched.
     191     *
     192     * @since 1.144.0
     193     * @param string $class_names Class names to add to the container.
     194     * @return void
     195     */
     196    private function render_loading_container( $class_names ) {
     197        ?>
     198        <div class="googlesitekit-preview-block <?php echo esc_attr( $class_names ); ?>">
     199            <div class="googlesitekit-preview-block__wrapper"></div>
     200        </div>
     201        <?php
     202    }
    137203}
  • google-site-kit/trunk/includes/Core/Authentication/Clients/OAuth_Client.php

    r3164469 r3221899  
    571571
    572572    /**
    573      * Determines whether the authentication proxy is used.
    574      *
    575      * In order to streamline the setup and authentication flow, the plugin uses a proxy mechanism based on an external
    576      * service. This can be overridden by providing actual GCP credentials with the {@see 'googlesitekit_oauth_secret'}
    577      * filter.
    578      *
    579      * @since 1.0.0
    580      * @deprecated 1.9.0
    581      *
    582      * @return bool True if proxy authentication is used, false otherwise.
    583      */
    584     public function using_proxy() {
    585         _deprecated_function( __METHOD__, '1.9.0', Credentials::class . '::using_proxy' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    586 
    587         return $this->credentials->using_proxy();
    588     }
    589 
    590     /**
    591573     * Determines whether the current owner ID must be changed or not.
    592574     *
  • google-site-kit/trunk/includes/Core/Key_Metrics/Key_Metrics_Settings.php

    r3208808 r3221899  
    4848    protected function get_default() {
    4949        return array(
    50             'widgetSlugs'                      => array(),
    51             'isWidgetHidden'                   => false,
    52             'includeConversionTailoredMetrics' => array(),
     50            'widgetSlugs'    => array(),
     51            'isWidgetHidden' => false,
    5352        );
    5453    }
     
    7271
    7372        $allowed_settings = array(
    74             'widgetSlugs'                      => true,
    75             'isWidgetHidden'                   => true,
    76             'includeConversionTailoredMetrics' => true,
     73            'widgetSlugs'    => true,
     74            'isWidgetHidden' => true,
    7775        );
    7876
     
    105103            }
    106104
    107             if ( isset( $settings['includeConversionTailoredMetrics'] ) ) {
    108                 $sanitized_settings['includeConversionTailoredMetrics'] = Sanitize::sanitize_string_list( $settings['includeConversionTailoredMetrics'] );
    109             }
    110 
    111105            return $sanitized_settings;
    112106        };
  • google-site-kit/trunk/includes/Core/Key_Metrics/REST_Key_Metrics_Controller.php

    r3201134 r3221899  
    185185                )
    186186            ),
    187             new REST_Route(
    188                 'core/user/data/reset-key-metrics-selection',
    189                 array(
    190                     'methods'             => WP_REST_Server::CREATABLE,
    191                     'callback'            => function () {
    192                         $this->settings->merge( array( 'widgetSlugs' => array() ) );
    193 
    194                         return new WP_REST_Response( $this->settings->get() );
    195                     },
    196                     'permission_callback' => $has_capabilities,
    197                 )
    198             ),
    199187        );
    200188    }
  • google-site-kit/trunk/includes/Core/Tags/First_Party_Mode/First_Party_Mode.php

    r3208808 r3221899  
    7272        $this->first_party_mode_settings = new First_Party_Mode_Settings( $options );
    7373        $this->rest_controller           = new REST_First_Party_Mode_Controller( $this, $this->first_party_mode_settings );
    74         $this->cron                      = new First_Party_Mode_Cron( array( $this, 'healthcheck' ) );
     74        $this->cron                      = new First_Party_Mode_Cron(
     75            $this->first_party_mode_settings,
     76            array( $this, 'healthcheck' )
     77        );
    7578    }
    7679
     
    184187     * @since 1.141.0
    185188     * @since 1.142.0 Relocated from REST_First_Party_Mode_Controller.
     189     * @since 1.144.0 Uses Google\FirstPartyLibrary\RequestHelper to send requests.
    186190     *
    187191     * @param string $endpoint The endpoint to check.
     
    189193     */
    190194    protected function is_endpoint_healthy( $endpoint ) {
    191         try {
    192             // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown,WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
    193             $response = file_get_contents( $endpoint );
    194         } catch ( \Exception $e ) {
     195        if ( ! defined( 'IS_FIRST_PARTY_MODE_TEST' ) ) {
     196            // TODO: This is a workaround to allow the measurement.php file to be loaded without making a
     197            // request, in order to use the RequestHelper class that it defines. We should find a better
     198            // solution in the future, but this will involve changes to the measurement.php file.
     199            define( 'IS_FIRST_PARTY_MODE_TEST', true );
     200        }
     201
     202        require_once GOOGLESITEKIT_PLUGIN_DIR_PATH . 'fpm/measurement.php';
     203
     204        $request_helper = new \Google\FirstPartyLibrary\RequestHelper();
     205
     206        $response = $request_helper->sendRequest( $endpoint );
     207
     208        if ( 200 !== $response['statusCode'] ) {
    195209            return false;
    196210        }
    197211
    198         if ( 'ok' !== $response ) {
     212        if ( 'ok' !== $response['body'] ) {
    199213            return false;
    200214        }
    201215
    202         return strpos( $http_response_header[0], '200 OK' ) !== false;
     216        return true;
    203217    }
    204218}
  • google-site-kit/trunk/includes/Core/Tags/First_Party_Mode/First_Party_Mode_Cron.php

    r3208808 r3221899  
    3030
    3131    /**
     32     * First_Party_Mode_Settings instance.
     33     *
     34     * @var First_Party_Mode_Settings
     35     */
     36    private $first_party_mode_settings;
     37
     38    /**
    3239     * Constructor.
    3340     *
    3441     * @since 1.142.0
    3542     *
    36      * @param callable $callback Function to call on the cron action.
     43     * @param First_Party_Mode_Settings $first_party_mode_settings First_Party_Mode_Settings instance.
     44     * @param callable                  $callback                  Function to call on the cron action.
    3745     */
    38     public function __construct( callable $callback ) {
    39         $this->cron_callback = $callback;
     46    public function __construct(
     47        First_Party_Mode_Settings $first_party_mode_settings,
     48        callable $callback
     49    ) {
     50        $this->first_party_mode_settings = $first_party_mode_settings;
     51        $this->cron_callback             = $callback;
    4052    }
    4153
     
    5567     */
    5668    public function maybe_schedule_cron() {
    57         if ( ! wp_next_scheduled( self::CRON_ACTION ) && ! wp_installing() ) {
     69        $settings    = $this->first_party_mode_settings->get();
     70        $fpm_enabled = $settings['isEnabled'];
     71
     72        if (
     73            $fpm_enabled &&
     74            ! wp_next_scheduled( self::CRON_ACTION ) &&
     75            ! wp_installing()
     76        ) {
    5877            wp_schedule_event( time(), 'hourly', self::CRON_ACTION );
    5978        }
  • google-site-kit/trunk/includes/Core/User/User.php

    r3141863 r3221899  
    1414
    1515/**
    16  * Class for handling audience settings rest routes.
     16 * Class for handling user settings rest routes.
    1717 *
    1818 * @since 1.134.0
     
    3131
    3232    /**
     33     * Conversion_Reporting instance.
     34     *
     35     * @since 1.144.0
     36     * @var Conversion_Reporting
     37     */
     38    private $conversion_reporting;
     39
     40    /**
    3341     * Constructor.
    3442     *
     
    3947    public function __construct( User_Options $user_options ) {
    4048        $this->audience_segmentation = new Audience_Segmentation( $user_options );
     49        $this->conversion_reporting  = new Conversion_Reporting( $user_options );
    4150    }
    4251
     
    4857    public function register() {
    4958        $this->audience_segmentation->register();
     59        $this->conversion_reporting->register();
    5060    }
    5161}
  • google-site-kit/trunk/includes/Core/User_Input/User_Input.php

    r3022626 r3221899  
    6868     */
    6969    private static $questions = array(
    70         'purpose'       => array(
     70        'purpose'                 => array(
    7171            'scope' => 'site',
    7272        ),
    73         'postFrequency' => array(
     73        'postFrequency'           => array(
    7474            'scope' => 'user',
    7575        ),
    76         'goals'         => array(
     76        'goals'                   => array(
    7777            'scope' => 'user',
     78        ),
     79        'includeConversionEvents' => array(
     80            'scope' => 'site',
    7881        ),
    7982    );
     
    200203            }
    201204        }
     205
     206        // Conversion events may be empty during setup if no events have been detected.
     207        // Since this setting does not affect whether user input is considered "set up",
     208        // we are excluding it from this check. It relates to user input initially being
     209        // set up with detected events or events added later.
     210        unset( $settings['includeConversionEvents'] );
    202211
    203212        foreach ( $settings as $setting ) {
  • google-site-kit/trunk/includes/Modules/AdSense.php

    r3201134 r3221899  
    749749            'name'        => _x( 'AdSense', 'Service name', 'google-site-kit' ),
    750750            'description' => __( 'Earn money by placing ads on your website. It’s free and easy.', 'google-site-kit' ),
    751             'order'       => 2,
    752751            'homepage'    => add_query_arg( $idenfifier_args, 'https://adsense.google.com/start' ),
    753752        );
  • google-site-kit/trunk/includes/Modules/Ads.php

    r3208808 r3221899  
    143143                    array(
    144144                        // When updating, mirror the fixed version for google-pax-sdk in package.json.
    145                         'src'          => 'https://www.gstatic.com/pax/1.0.12/pax_integrator.js',
     145                        'src'          => 'https://www.gstatic.com/pax/1.1.0/pax_integrator.js',
    146146                        'execution'    => 'async',
    147147                        'dependencies' => array(
     
    209209            'name'        => _x( 'Ads', 'Service name', 'google-site-kit' ),
    210210            'description' => Feature_Flags::enabled( 'adsPax' ) ? __( 'Grow sales, leads or awareness for your business by advertising with Google Ads', 'google-site-kit' ) : __( 'Track conversions for your existing Google Ads campaigns', 'google-site-kit' ),
    211             'order'       => 1,
    212211            'homepage'    => __( 'https://google.com/ads', 'google-site-kit' ),
    213212        );
  • google-site-kit/trunk/includes/Modules/Ads/Web_Tag.php

    r3075250 r3221899  
    1414use Google\Site_Kit\Core\Tags\GTag;
    1515use Google\Site_Kit\Core\Tags\Tag_With_Linker_Interface;
     16use Google\Site_Kit\Core\Tags\Tag_With_Linker_Trait;
    1617use Google\Site_Kit\Core\Util\Method_Proxy_Trait;
    1718
     
    2627
    2728    use Method_Proxy_Trait;
    28 
    29     /**
    30      * Sets the current home domain.
    31      *
    32      * @since 1.125.0
    33      *
    34      * @param string $domain Domain name.
    35      */
    36     public function set_home_domain( $domain ) {
    37         $this->home_domain = $domain;
    38     }
     29    use Tag_With_Linker_Trait;
    3930
    4031    /**
  • google-site-kit/trunk/includes/Modules/Analytics_4.php

    r3208808 r3221899  
    9393use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_Cron;
    9494use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_Events_Sync;
     95use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_New_Badge_Events_Sync;
    9596use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_Provider;
    9697use Google\Site_Kit\Modules\Analytics_4\Reset_Audiences;
    9798use stdClass;
    9899use WP_Error;
     100use WP_Post;
    99101
    100102/**
     
    706708        }
    707709
    708         if ( Feature_Flags::enabled( 'conversionReporting' ) ) {
    709             $datapoints['POST:clear-conversion-reporting-new-events']  = array(
    710                 'service' => '',
    711             );
    712             $datapoints['POST:clear-conversion-reporting-lost-events'] = array(
    713                 'service' => '',
    714             );
    715         }
    716 
    717710        return $datapoints;
    718711    }
     
    14591452                $custom_dimension->setParameterName( $custom_dimension_data['parameterName'] );
    14601453                $custom_dimension->setDisplayName( $custom_dimension_data['displayName'] );
    1461                 $custom_dimension->setDescription( $custom_dimension_data['description'] );
    14621454                $custom_dimension->setScope( $custom_dimension_data['scope'] );
    1463                 $custom_dimension->setDisallowAdsPersonalization( $custom_dimension_data['disallowAdsPersonalization'] );
     1455
     1456                if ( isset( $custom_dimension_data['description'] ) ) {
     1457                    $custom_dimension->setDescription( $custom_dimension_data['description'] );
     1458                }
     1459
     1460                if ( isset( $custom_dimension_data['disallowAdsPersonalization'] ) ) {
     1461                    $custom_dimension->setDisallowAdsPersonalization( $custom_dimension_data['disallowAdsPersonalization'] );
     1462                }
    14641463
    14651464                $analyticsadmin = $this->get_service( 'analyticsadmin' );
     
    16841683                return function () use ( $data ) {
    16851684                    return $this->transients->set( 'googlesitekit_inline_tag_id_mismatch', $data['hasMismatchedTag'] );
    1686                 };
    1687             case 'POST:clear-conversion-reporting-new-events':
    1688                 return function () {
    1689                     return $this->transients->delete( Conversion_Reporting_Events_Sync::DETECTED_EVENTS_TRANSIENT );
    1690                 };
    1691             case 'POST:clear-conversion-reporting-lost-events':
    1692                 return function () {
    1693                     return $this->transients->delete( Conversion_Reporting_Events_Sync::LOST_EVENTS_TRANSIENT );
    16941685                };
    16951686        }
     
    18321823            'name'        => _x( 'Analytics', 'Service name', 'google-site-kit' ),
    18331824            'description' => __( 'Get a deeper understanding of your customers. Google Analytics gives you the free tools you need to analyze data for your business in one place.', 'google-site-kit' ),
    1834             'order'       => 3,
    18351825            'homepage'    => __( 'https://analytics.google.com/analytics/web', 'google-site-kit' ),
    18361826        );
     
    20402030        $post = get_queried_object();
    20412031
     2032        if ( ! $post instanceof WP_Post ) {
     2033            return $data;
     2034        }
     2035
    20422036        if ( in_array( 'googlesitekit_post_type', $settings['availableCustomDimensions'], true ) ) {
    20432037            $data['googlesitekit_post_type'] = $post->post_type;
     
    26142608        }
    26152609
    2616         $detected_events                           = $this->transients->get( Conversion_Reporting_Events_Sync::DETECTED_EVENTS_TRANSIENT );
    2617         $lost_events                               = $this->transients->get( Conversion_Reporting_Events_Sync::LOST_EVENTS_TRANSIENT );
    2618         $modules_data['analytics-4']['newEvents']  = is_array( $detected_events ) ? $detected_events : array();
    2619         $modules_data['analytics-4']['lostEvents'] = is_array( $lost_events ) ? $lost_events : array();
     2610        $detected_events  = $this->transients->get( Conversion_Reporting_Events_Sync::DETECTED_EVENTS_TRANSIENT );
     2611        $lost_events      = $this->transients->get( Conversion_Reporting_Events_Sync::LOST_EVENTS_TRANSIENT );
     2612        $new_events_badge = $this->transients->get( Conversion_Reporting_New_Badge_Events_Sync::NEW_EVENTS_BADGE_TRANSIENT );
     2613
     2614        $modules_data['analytics-4']['newEvents']      = is_array( $detected_events ) ? $detected_events : array();
     2615        $modules_data['analytics-4']['lostEvents']     = is_array( $lost_events ) ? $lost_events : array();
     2616        $modules_data['analytics-4']['newBadgeEvents'] = is_array( $new_events_badge ) ? $new_events_badge['events'] : array();
    26202617
    26212618        return $modules_data;
  • google-site-kit/trunk/includes/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Events_Sync.php

    r3181737 r3221899  
    1414use Google\Site_Kit\Modules\Analytics_4\Settings;
    1515use Google\Site_Kit\Core\Storage\Transients;
    16 use Google\Site_Kit\Context;
    1716
    1817/**
     
    5857
    5958    /**
     59     * Conversion_Reporting_New_Badge_Events_Sync instance.
     60     *
     61     * @var Conversion_Reporting_New_Badge_Events_Sync
     62     */
     63    private $new_badge_events_sync;
     64
     65    /**
    6066     * Transients instance.
    6167     *
     
    7076     * @since 1.135.0
    7177     * @since 1.139.0 Added $context param to constructor.
     78     * @since 1.144.0 Added $transients and $new_badge_events_sync params to constructor, and removed $context.
    7279     *
    73      * @param Context     $context   Plugin context.
    74      * @param Settings    $settings  Settings module settings instance.
    75      * @param Analytics_4 $analytics Analytics 4 module instance.
     80     * @param Settings                                   $settings              Settings module settings instance.
     81     * @param Transients                                 $transients            Transients instance.
     82     * @param Analytics_4                                $analytics             Analytics 4 module instance.
     83     * @param Conversion_Reporting_New_Badge_Events_Sync $new_badge_events_sync Conversion_Reporting_New_Badge_Events_Sync instance.
    7684     */
    7785    public function __construct(
    78         Context $context,
    7986        Settings $settings,
    80         Analytics_4 $analytics
     87        Transients $transients,
     88        Analytics_4 $analytics,
     89        Conversion_Reporting_New_Badge_Events_Sync $new_badge_events_sync
    8190    ) {
    82         $this->settings   = $settings;
    83         $this->analytics  = $analytics;
    84         $this->transients = new Transients( $context );
     91        $this->settings              = $settings;
     92        $this->transients            = $transients;
     93        $this->analytics             = $analytics;
     94        $this->new_badge_events_sync = $new_badge_events_sync;
    8595    }
    8696
     
    118128            $detected_events[] = $row['dimensionValues'][0]['value'];
    119129        }
     130        $settings_partial = array( 'detectedEvents' => $detected_events );
    120131
     132        $this->maybe_update_new_and_lost_events(
     133            $detected_events,
     134            $saved_detected_events,
     135            $settings_partial
     136        );
     137
     138        $this->settings->merge( $settings_partial );
     139    }
     140
     141    /**
     142     * Saves new and lost events transients.
     143     *
     144     * @since 1.144.0
     145     *
     146     * @param array $detected_events       Currently detected events array.
     147     * @param array $saved_detected_events Previously saved detected events array.
     148     * @param array $settings_partial      Analaytics settings partial.
     149     */
     150    protected function maybe_update_new_and_lost_events( $detected_events, $saved_detected_events, &$settings_partial ) {
    121151        $new_events  = array_diff( $detected_events, $saved_detected_events );
    122152        $lost_events = array_diff( $saved_detected_events, $detected_events );
     
    124154        if ( ! empty( $new_events ) ) {
    125155            $this->transients->set( self::DETECTED_EVENTS_TRANSIENT, array_values( $new_events ) );
     156            $this->new_badge_events_sync->sync_new_badge_events( $new_events );
     157            $settings_partial['newConversionEventsLastUpdateAt'] = time();
    126158        }
    127159
    128160        if ( ! empty( $lost_events ) ) {
    129161            $this->transients->set( self::LOST_EVENTS_TRANSIENT, array_values( $lost_events ) );
     162            $settings_partial['lostConversionEventsLastUpdateAt'] = time();
    130163        }
    131164
     
    133166            $this->transients->set( self::DETECTED_EVENTS_TRANSIENT, $detected_events );
    134167        }
    135 
    136         $this->settings->merge( array( 'detectedEvents' => $detected_events ) );
    137168    }
    138169
  • google-site-kit/trunk/includes/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Provider.php

    r3181737 r3221899  
    1212
    1313use Google\Site_Kit\Context;
     14use Google\Site_Kit\Core\Storage\Transients;
    1415use Google\Site_Kit\Core\Storage\User_Options;
    1516use Google\Site_Kit\Modules\Analytics_4;
     
    7374        $this->analytics    = $analytics;
    7475
    75         $this->events_sync = new Conversion_Reporting_Events_Sync( $context, $settings, $this->analytics );
    76         $this->cron        = new Conversion_Reporting_Cron( fn() => $this->cron_callback() );
     76        $transients            = new Transients( $context );
     77        $new_badge_events_sync = new Conversion_Reporting_New_Badge_Events_Sync( $transients );
     78        $this->events_sync     = new Conversion_Reporting_Events_Sync(
     79            $settings,
     80            $transients,
     81            $this->analytics,
     82            $new_badge_events_sync
     83        );
     84        $this->cron            = new Conversion_Reporting_Cron( fn() => $this->cron_callback() );
    7785    }
    7886
  • google-site-kit/trunk/includes/Modules/Analytics_4/Settings.php

    r3181737 r3221899  
    7575            'audienceSegmentationSetupCompletedBy',
    7676            'detectedEvents',
     77            'newConversionEventsLastUpdateAt',
     78            'lostConversionEventsLastUpdateAt',
    7779        );
    7880    }
     
    111113            'audienceSegmentationSetupCompletedBy' => null,
    112114            'detectedEvents'                       => array(),
     115            'newConversionEventsLastUpdateAt'      => 0,
     116            'lostConversionEventsLastUpdateAt'     => 0,
    113117        );
    114118    }
     
    214218                    }
    215219                }
     220
     221                if ( isset( $option['newConversionEventsLastUpdateAt'] ) ) {
     222                    if ( ! is_int( $option['newConversionEventsLastUpdateAt'] ) ) {
     223                        $option['newConversionEventsLastUpdateAt'] = 0;
     224                    }
     225                }
     226
     227                if ( isset( $option['lostConversionEventsLastUpdateAt'] ) ) {
     228                    if ( ! is_int( $option['lostConversionEventsLastUpdateAt'] ) ) {
     229                        $option['lostConversionEventsLastUpdateAt'] = 0;
     230                    }
     231                }
    216232            }
    217233
  • google-site-kit/trunk/includes/Modules/PageSpeed_Insights.php

    r3118692 r3221899  
    181181            'name'        => _x( 'PageSpeed Insights', 'Service name', 'google-site-kit' ),
    182182            'description' => __( 'Google PageSpeed Insights gives you metrics about performance, accessibility, SEO and PWA', 'google-site-kit' ),
    183             'order'       => 4,
    184183            'homepage'    => __( 'https://pagespeed.web.dev', 'google-site-kit' ),
    185184        );
  • google-site-kit/trunk/includes/Modules/Reader_Revenue_Manager.php

    r3201134 r3221899  
    333333            'name'        => _x( 'Reader Revenue Manager', 'Service name', 'google-site-kit' ),
    334334            'description' => __( 'Reader Revenue Manager helps publishers grow, retain, and engage their audiences, creating new revenue opportunities', 'google-site-kit' ),
    335             'order'       => 5,
    336335            'homepage'    => 'https://publishercenter.google.com',
    337336        );
  • google-site-kit/trunk/includes/Modules/Sign_In_With_Google.php

    r3208808 r3221899  
    127127        add_action( 'admin_action_' . self::ACTION_DISCONNECT, fn () => $this->handle_disconnect_user() );
    128128
    129         add_action( 'login_form', $this->get_method_proxy( 'render_signin_button' ) );
    130 
    131129        add_action( 'show_user_profile', $this->get_method_proxy( 'render_disconnect_profile' ) ); // This action shows the disconnect section on the users own profile page.
    132130        add_action( 'edit_user_profile', $this->get_method_proxy( 'render_disconnect_profile' ) ); // This action shows the disconnect section on other users profile page to allow admins to disconnect others.
    133131
    134         add_action( 'woocommerce_login_form_start', $this->get_method_proxy( 'render_signin_button' ) );
     132        // (Potentially) render the Sign in with Google script tags/buttons.
     133        add_action( 'wp_footer', $this->get_method_proxy( 'render_signinwithgoogle' ) );
     134        // Output the Sign in with Google JS on the WordPress login page.
     135        add_action( 'login_footer', $this->get_method_proxy( 'render_signinwithgoogle' ) );
    135136
    136137        // Delete client ID stored from previous module connection on module reconnection.
     
    227228            'name'        => _x( 'Sign in with Google', 'Service name', 'google-site-kit' ),
    228229            'description' => __( 'Improve user engagement, trust and data privacy, while creating a simple, secure and personalized experience for your visitors', 'google-site-kit' ),
    229             'order'       => 10,
    230230            'homepage'    => __( 'https://developers.google.com/identity/gsi/web/guides/overview', 'google-site-kit' ),
    231231        );
     
    289289
    290290    /**
    291      * Renders the sign in button.
     291     * Renders the Sign in with Google JS script tags, One-tap code, and
     292     * buttons.
    292293     *
    293294     * @since 1.139.0
    294      */
    295     private function render_signin_button() {
     295     * @since 1.144.0 Renamed to `render_signinwithgoogle` and conditionally
     296     *                rendered the code to replace buttons.
     297     */
     298    private function render_signinwithgoogle() {
    296299        global $wp;
     300        $is_wp_login           = is_login();
    297301        $is_woo_commerce_login = 'my-account' === $wp->request;
    298302
    299303        $settings = $this->get_settings()->get();
     304
     305        // If there's no client ID available, don't render the button.
    300306        if ( ! $settings['clientID'] ) {
     307            return;
     308        }
     309
     310        // If this is not the WordPress or WooCommerce login page, check to
     311        // see if "One-tap enabled on all pages" is set first. If it isnt:
     312        // don't render the Sign in with Google JS.
     313        if ( ! $is_wp_login && ! $is_woo_commerce_login && ! $settings['oneTapOnAllPages'] ) {
    301314            return;
    302315        }
     
    317330            'shape' => $settings['shape'],
    318331        );
     332
     333        // Whether buttons will be rendered/transformed on this page.
     334        $render_buttons = $is_wp_login || $is_woo_commerce_login;
    319335
    320336        // Render the Sign in with Google button and related inline styles.
     
    329345        ?>
    330346( () => {
    331     const parent = document.createElement( 'div' );
    332 <?php if ( $is_woo_commerce_login ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    333     document.getElementsByClassName( 'login' )[0]?.insertBefore( parent, document.getElementsByClassName( 'woocommerce-form-row' )[0] );
    334         <?php else : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    335     document.getElementById( 'login' ).insertBefore( parent, document.getElementById( 'loginform' ) );
     347    <?php if ( $render_buttons ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     348        const parent = document.createElement( 'div' );
     349
     350        <?php if ( $is_wp_login ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     351            document.getElementById( 'login' ).insertBefore( parent, document.getElementById( 'loginform' ) );
    336352        <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     353
     354        <?php if ( $is_woo_commerce_login ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     355            document.getElementsByClassName( 'login' )[0]?.insertBefore( parent, document.getElementsByClassName( 'woocommerce-form-row' )[0] );
     356        <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     357    <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    337358
    338359    async function handleCredentialResponse( response ) {
     
    342363                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    343364                body: new URLSearchParams( response )
    344             });
     365            } );
    345366            if ( res.ok && res.redirected ) {
    346367                location.assign( res.url );
     
    354375        client_id: '<?php echo esc_js( $settings['clientID'] ); ?>',
    355376        callback: handleCredentialResponse,
     377        library_name: 'Site-Kit',
    356378    } );
    357379
    358     google.accounts.id.renderButton( parent, <?php echo wp_json_encode( $btn_args ); ?> );
    359 
    360 <?php if ( $settings['oneTapEnabled'] ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    361     google.accounts.id.prompt();
    362         <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    363 
    364 <?php if ( ! empty( $redirect_to ) ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    365     const expires = new Date();
    366     expires.setTime( expires.getTime() + 1000 * 60 * 5 );
    367     document.cookie = "<?php echo esc_js( Authenticator::COOKIE_REDIRECT_TO ); ?>=<?php echo esc_js( $redirect_to ); ?>;expires="  + expires.toUTCString() + ";path=<?php echo esc_js( Authenticator::get_cookie_path() ); ?>";
    368         <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     380    <?php if ( $render_buttons ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     381        google.accounts.id.renderButton( parent, <?php echo wp_json_encode( $btn_args ); ?> );
     382    <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     383
     384    <?php if ( $settings['oneTapEnabled'] && ( $is_wp_login || ! is_user_logged_in() ) ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     385        google.accounts.id.prompt();
     386    <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     387
     388    <?php if ( $render_buttons && ! empty( $redirect_to ) ) : // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
     389        const expires = new Date();
     390        expires.setTime( expires.getTime() + 1000 * 60 * 5 );
     391        document.cookie = "<?php echo esc_js( Authenticator::COOKIE_REDIRECT_TO ); ?>=<?php echo esc_js( $redirect_to ); ?>;expires="  + expires.toUTCString() + ";path=<?php echo esc_js( Authenticator::get_cookie_path() ); ?>";
     392    <?php endif; // phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect ?>
    369393} )();
    370394        <?php
    371395        BC_Functions::wp_print_inline_script_tag( ob_get_clean() );
    372         printf( "\n<!-- %s -->\n", esc_html__( 'End Sign in with Google button added by Site Kit', 'google-site-kit' ) );
     396        print( "\n<!-- End Sign in with Google button added by Site Kit -->\n" );
    373397    }
    374398
  • google-site-kit/trunk/includes/Modules/Sign_In_With_Google/Settings.php

    r3191565 r3221899  
    8787    protected function get_default() {
    8888        return array(
    89             'clientID'      => '',
    90             'text'          => self::TEXT_SIGN_IN_WITH_GOOGLE['value'],
    91             'theme'         => self::THEME_LIGHT['value'],
    92             'shape'         => self::SHAPE_RECTANGULAR['value'],
    93             'oneTapEnabled' => false,
     89            'clientID'         => '',
     90            'text'             => self::TEXT_SIGN_IN_WITH_GOOGLE['value'],
     91            'theme'            => self::THEME_LIGHT['value'],
     92            'shape'            => self::SHAPE_RECTANGULAR['value'],
     93            'oneTapEnabled'    => false,
     94            'oneTapOnAllPages' => false,
    9495        );
    9596    }
     
    152153            }
    153154
     155            if ( isset( $option['oneTapOnAllPages'] ) ) {
     156                $option['oneTapOnAllPages'] = (bool) $option['oneTapOnAllPages'];
     157            }
     158
    154159            return $option;
    155160        };
  • google-site-kit/trunk/includes/Modules/Tag_Manager.php

    r3208808 r3221899  
    467467            'name'        => _x( 'Tag Manager', 'Service name', 'google-site-kit' ),
    468468            'description' => __( 'Tag Manager creates an easy to manage way to create tags on your site without updating code', 'google-site-kit' ),
    469             'order'       => 6,
    470469            'homepage'    => __( 'https://tagmanager.google.com/', 'google-site-kit' ),
    471470        );
  • google-site-kit/trunk/includes/vendor/composer/autoload_classmap.php

    r3208808 r3221899  
    196196    'Google\\Site_Kit\\Core\\User\\Audience_Segmentation' => $baseDir . '/Core/User/Audience_Segmentation.php',
    197197    'Google\\Site_Kit\\Core\\User\\Audience_Settings' => $baseDir . '/Core/User/Audience_Settings.php',
     198    'Google\\Site_Kit\\Core\\User\\Conversion_Reporting' => $baseDir . '/Core/User/Conversion_Reporting.php',
     199    'Google\\Site_Kit\\Core\\User\\Conversion_Reporting_Settings' => $baseDir . '/Core/User/Conversion_Reporting_Settings.php',
    198200    'Google\\Site_Kit\\Core\\User\\REST_Audience_Settings_Controller' => $baseDir . '/Core/User/REST_Audience_Settings_Controller.php',
     201    'Google\\Site_Kit\\Core\\User\\REST_Conversion_Reporting_Controller' => $baseDir . '/Core/User/REST_Conversion_Reporting_Controller.php',
    199202    'Google\\Site_Kit\\Core\\User\\User' => $baseDir . '/Core/User/User.php',
    200203    'Google\\Site_Kit\\Core\\User_Input\\REST_User_Input_Controller' => $baseDir . '/Core/User_Input/REST_User_Input_Controller.php',
     
    269272    'Google\\Site_Kit\\Modules\\Analytics_4\\Conversion_Reporting\\Conversion_Reporting_Cron' => $baseDir . '/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Cron.php',
    270273    'Google\\Site_Kit\\Modules\\Analytics_4\\Conversion_Reporting\\Conversion_Reporting_Events_Sync' => $baseDir . '/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Events_Sync.php',
     274    'Google\\Site_Kit\\Modules\\Analytics_4\\Conversion_Reporting\\Conversion_Reporting_New_Badge_Events_Sync' => $baseDir . '/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_New_Badge_Events_Sync.php',
    271275    'Google\\Site_Kit\\Modules\\Analytics_4\\Conversion_Reporting\\Conversion_Reporting_Provider' => $baseDir . '/Modules/Analytics_4/Conversion_Reporting/Conversion_Reporting_Provider.php',
    272276    'Google\\Site_Kit\\Modules\\Analytics_4\\Custom_Dimensions_Data_Available' => $baseDir . '/Modules/Analytics_4/Custom_Dimensions_Data_Available.php',
  • google-site-kit/trunk/readme.txt

    r3208808 r3221899  
    55Tested up to:      6.7
    66Requires PHP:      7.4
    7 Stable tag:        1.142.0
     7Stable tag:        1.144.0
    88License:           Apache License 2.0
    99License URI:       https://www.apache.org/licenses/LICENSE-2.0
     
    110110== Changelog ==
    111111
    112 = 1.142.0 =
     112= 1.144.0 =
    113113
    114114**Added**
    115115
    116 * Add Analytics events to Sign in with Google. See [#9747](https://github.com/google/site-kit-wp/issues/9747).
     116* Add `library_name` parameter to Sign in with Google button. See [#9924](https://github.com/google/site-kit-wp/issues/9924).
     117* Add incremental ESLint rule to avoid defining `scenario.label` on stories. See [#9865](https://github.com/google/site-kit-wp/issues/9865).
     118* Add option to enable "One-tap" sign-in across site when using Sign in with Google. See [#9861](https://github.com/google/site-kit-wp/issues/9861).
    117119
    118120**Enhanced**
    119121
    120 * Fix the "improve your measurement" section's layout in mobile viewports. See [#9830](https://github.com/google/site-kit-wp/issues/9830).
    121 * Update the default value of the First-party mode `isEnabled` setting to `false`. See [#9828](https://github.com/google/site-kit-wp/issues/9828).
    122 * Add periodic server requirement health checks for first-party mode. See [#9768](https://github.com/google/site-kit-wp/issues/9768).
    123 * Always display the "Anyone can register" WordPress setting in Sign in with Google settings. See [#9735](https://github.com/google/site-kit-wp/issues/9735).
    124 * Update learn more link in Sign in with Google module settings. See [#9734](https://github.com/google/site-kit-wp/issues/9734).
    125 * Update copy in Sign in with Google "Connect more services" UI. See [#9733](https://github.com/google/site-kit-wp/issues/9733).
    126 * Update Sign in with Google setup success notification UI. See [#9724](https://github.com/google/site-kit-wp/issues/9724).
    127 * Automatically dismiss the First-Party Mode setup banner notification when the toggle is enabled from the settings screen, preventing redundant notifications. See [#9698](https://github.com/google/site-kit-wp/issues/9698).
    128 * Add a selector to detect changes and an action to reset First-party mode settings, integrated with Analytics and Ads rollback and validation processes. See [#9688](https://github.com/google/site-kit-wp/issues/9688).
    129 * Add FPFE health check and script access statuses to Site Kit’s Site Health section, displaying whether these checks are enabled or disabled. See [#9668](https://github.com/google/site-kit-wp/issues/9668).
    130 * Add First-Party Mode status to Site Kit’s Site Health section, displaying whether the feature is enabled or not when either the Analytics or Ads modules are connected and the `firstPartyMode` feature flag is active. See [#9667](https://github.com/google/site-kit-wp/issues/9667).
    131 * Add support for gtag to load in first-party mode when enabled. See [#9664](https://github.com/google/site-kit-wp/issues/9664).
    132 * Display the First-party mode enabled status in the Ads settings view. See [#9659](https://github.com/google/site-kit-wp/issues/9659).
    133 * Display the First-party mode enabled status in the Analytics settings view. See [#9658](https://github.com/google/site-kit-wp/issues/9658).
    134 * Integrate the First-party mode toggle into the Ads module’s settings form, allowing users to enable or disable First-party mode. See [#9655](https://github.com/google/site-kit-wp/issues/9655).
    135 * Integrate the First-party mode toggle into the Analytics module’s settings form, allowing users to enable or disable First-party mode. See [#9654](https://github.com/google/site-kit-wp/issues/9654).
    136 * Group measurement toggles together on the settings screen in the Ads and Analytics module edit sections. See [#9651](https://github.com/google/site-kit-wp/issues/9651).
    137 * Add a "Beta" badge to the First-party mode toggle. See [#9650](https://github.com/google/site-kit-wp/issues/9650).
    138 * Implement the First-party mode toggle as a component which is presented in Storybook. See [#9649](https://github.com/google/site-kit-wp/issues/9649).
    139 * Add first-party mode setup success notification. See [#9648](https://github.com/google/site-kit-wp/issues/9648).
    140 * Add the First-party mode setup banner to let users know about the feature and enable it from the dashboard. See [#9647](https://github.com/google/site-kit-wp/issues/9647).
    141 * Update spacing between CTA actions for consistency. See [#9600](https://github.com/google/site-kit-wp/issues/9600).
    142 * Add notification banner when event data has been missing for ninety days. See [#9578](https://github.com/google/site-kit-wp/issues/9578).
    143 * Improve notifications rendering performance. See [#9488](https://github.com/google/site-kit-wp/issues/9488).
    144 * Add full size selection panel on the new screen. See [#9375](https://github.com/google/site-kit-wp/issues/9375).
    145 * Update Analytics Conversion Report notifications to be more context-aware. See [#9373](https://github.com/google/site-kit-wp/issues/9373).
    146 * Ensure Analytics Conversion Reports notification appears for users who set up Key Metrics manually. See [#9372](https://github.com/google/site-kit-wp/issues/9372).
    147 * Ensure that the setup flow for a module is automatically continued when clicking the "Redo setup" CTA on the "Site Kit can’t access necessary data" unsatisfied scopes notification. See [#9261](https://github.com/google/site-kit-wp/issues/9261).
    148 * Extend Consent Mode conditions logic. See [#9147](https://github.com/google/site-kit-wp/issues/9147).
     122* Add the `rrmModuleV2` feature flag, this will be used for phase two of the Reader Revenue Manager module's development. See [#9948](https://github.com/google/site-kit-wp/issues/9948).
     123* Update FPM health check to use the approach from the measurement script. See [#9916](https://github.com/google/site-kit-wp/issues/9916).
     124* Improve Analytics Conversion Reporting new/lost events callouts experience for each Site Kit user. See [#9897](https://github.com/google/site-kit-wp/issues/9897).
     125* Update subtle notification padding for consistency with the Figma design. See [#9860](https://github.com/google/site-kit-wp/issues/9860).
     126* Add a loading spinner to the "Enable First-party mode" CTA button on the setup banner to indicate progress during the setup process. See [#9856](https://github.com/google/site-kit-wp/issues/9856).
     127* Only run the periodic server requirement health checks for First-party mode when the mode is enabled. See [#9842](https://github.com/google/site-kit-wp/issues/9842).
     128* Update Partner Ads Experience with knowledge of supported conversion events. See [#9816](https://github.com/google/site-kit-wp/issues/9816).
     129* Improve logic for persisting badges in the Key Metrics selection panel. See [#9798](https://github.com/google/site-kit-wp/issues/9798).
     130* Add the Suggested group to the key metrics selection panel. See [#9797](https://github.com/google/site-kit-wp/issues/9797).
     131* Add a warning notification on the dashboard to alert users when First-party mode is disabled due to failed server requirement checks. See [#9767](https://github.com/google/site-kit-wp/issues/9767).
     132* Update to the latest version of the First-party mode proxy script. See [#9710](https://github.com/google/site-kit-wp/issues/9710).
     133* Add "Learn more" links for First-party mode. See [#9699](https://github.com/google/site-kit-wp/issues/9699).
     134* Introduce GA4 tracking events for the First-party mode feature. See [#9669](https://github.com/google/site-kit-wp/issues/9669).
     135* Add loading state with placeholder elements to Site Kit's WP dashboard widget. See [#9570](https://github.com/google/site-kit-wp/issues/9570).
     136* Fix issues with Audience Creation Notice when browser viewport is very short. See [#9562](https://github.com/google/site-kit-wp/issues/9562).
     137* Improve accuracy of periodic network connection check. See [#9485](https://github.com/google/site-kit-wp/issues/9485).
     138* Add badge to new Analytics Conversion Reporting widget tiles and groups. See [#9386](https://github.com/google/site-kit-wp/issues/9386).
     139* Update the Setup Error Banner notification to use the new Notifications API. See [#9283](https://github.com/google/site-kit-wp/issues/9283).
     140* Move settings edit dependency loading state to module stores. See [#8730](https://github.com/google/site-kit-wp/issues/8730).
     141* Improve the "See full details" link in AdSense settings, linking to the list of sites for the account where possible. See [#8076](https://github.com/google/site-kit-wp/issues/8076).
     142* Ensure that cities and countries with unset values don't show up in the "Top cities driving traffic" and "Top countries driving traffic" Key Metric tiles. See [#7884](https://github.com/google/site-kit-wp/issues/7884).
     143
     144**Changed**
     145
     146* Remove the deprecated `OAuth_Client::using_proxy` method and its associated tests. See [#8366](https://github.com/google/site-kit-wp/issues/8366).
    149147
    150148**Fixed**
    151149
    152 * Update the Sign in with Google module to suggest using the previous client ID when re-connecting the module. See [#9744](https://github.com/google/site-kit-wp/issues/9744).
    153 * Ensure Sign in with Google translations are consistent. See [#9738](https://github.com/google/site-kit-wp/issues/9738).
    154 * Add Sign in with Google live preview in settings. See [#9718](https://github.com/google/site-kit-wp/issues/9718).
    155 * Update layout of Top Content widget in smaller viewports to use a tab per metric column. See [#7563](https://github.com/google/site-kit-wp/issues/7563).
     150* Ensure measurement tracking requests succeed when both the Analytics and Ads modules are connected and First-party mode is enabled. See [#9901](https://github.com/google/site-kit-wp/issues/9901).
     151* Improve sort order in module list. See [#9877](https://github.com/google/site-kit-wp/issues/9877).
     152* Ensure "Enhanced Measurement" setting is not activated when disabled during Analytics setup. See [#9827](https://github.com/google/site-kit-wp/issues/9827).
     153* Fix a glitch where setup CTA banners would momentarily appear again when dismissing their admin settings tooltip. See [#9791](https://github.com/google/site-kit-wp/issues/9791).
     154* Fix iPad 10 Safari inconsistencies. See [#9776](https://github.com/google/site-kit-wp/issues/9776).
     155* Fix potential for PHP warning related to accessing a property `post_type` on null. See [#9762](https://github.com/google/site-kit-wp/issues/9762).
     156* Ensure Site Kit's Google chart on the WordPress dashboard widget correctly adapts to viewport width changes. See [#9756](https://github.com/google/site-kit-wp/issues/9756).
     157* Fix the deprecation error in the Ads module related to the creation of a dynamic property in the `Web_Tag` class. See [#9531](https://github.com/google/site-kit-wp/issues/9531).
     158* Prevent unnecessary requests on dashboard. See [#9178](https://github.com/google/site-kit-wp/issues/9178).
     159* Prevent PHP warnings when creating custom dimensions. See [#7801](https://github.com/google/site-kit-wp/issues/7801).
    156160
    157161[See changelog for all versions](https://raw.githubusercontent.com/google/site-kit-wp/main/changelog.txt).
Note: See TracChangeset for help on using the changeset viewer.