aiwp = AIWP(); $this->quotauser = 'u' . get_current_user_id() . 's' . get_current_blog_id(); $security = wp_create_nonce( 'aiwp_state' ); if ( $this->aiwp->config->options['user_api'] ) { $this->client_id = $this->aiwp->config->options['client_id']; $this->client_secret = $this->aiwp->config->options['client_secret']; if ( is_multisite() && $this->aiwp->config->options['network_mode'] ) { $redirect_uri = network_admin_url( 'admin.php?page=aiwp_settings' ); } else { $redirect_uri = admin_url( 'admin.php?page=aiwp_settings' ); } $this->redirect_uri = $redirect_uri; $this->token_uri = 'https://oauth2.googleapis.com/token'; $this->revoke_uri = 'https://oauth2.googleapis.com/revoke'; $this->state = $security; } else { $this->client_id = '220758964178-rhheb4146405g3fs6e4qjkk0rnf5q9q5.apps.googleusercontent.com'; $this->client_secret = 'GOCSPX'; $this->redirect_uri = AIWP_ENDPOINT_URL . 'oauth2callback.php'; $this->token_uri = AIWP_ENDPOINT_URL . 'aiwp-token.php'; $this->revoke_uri = AIWP_ENDPOINT_URL . 'aiwp-revoke.php'; if ( is_multisite() && $this->aiwp->config->options['network_mode'] ) { $state_uri = network_admin_url( 'admin.php?page=aiwp_settings' ) . '&state=' . $security; } else { $state_uri = admin_url( 'admin.php?page=aiwp_settings' ) . '&state=' . $security; } $this->state = $state_uri; } if ( $this->aiwp->config->options['token'] ) { $this->refresh_token(); } } /** * Creates the oauth2 link for Google API authorization * @return string */ public function createAuthUrl() { $scope = 'https://www.googleapis.com/auth/analytics.readonly'; // @formatter:off $auth_url = 'https://accounts.google.com/o/oauth2/v2/auth?'; $query_arr = array( 'client_id' => $this->client_id, 'redirect_uri' => $this->redirect_uri, 'response_type' => 'code', 'scope' => $scope, 'state' => $this->state, 'access_type' => 'offline', 'prompt' => 'consent', ); // @formatter:on $auth_url = $auth_url . http_build_query( $query_arr ); return $auth_url; } /** * Handles the exchange of an access code with a token * @param string $access_code * @return string|mixed */ public function authenticate( $access_code ) { // @formatter:off $token_data = array( 'client_id' => $this->client_id, 'client_secret' => $this->client_secret, 'code' => $access_code, 'redirect_uri' => $this->redirect_uri, 'grant_type' => 'authorization_code', ); $request_args = array( 'body' => $token_data, 'headers' => array( 'Referer' => AIWP_CURRENT_VERSION ) ); // @formatter:on $response = wp_remote_post( $this->token_uri, $request_args ); if ( is_wp_error( $response ) ) { $timeout = $this->get_timeouts(); AIWP_Tools::set_error( $response, $timeout ); return false; } $body = wp_remote_retrieve_body( $response ); $token = json_decode( $body, true ); if ( isset( $token['error'] ) ) { $timeout = $this->get_timeouts(); $error = new WP_Error(); if ( isset( $token['error']['code'] ) && isset( $token['error']['status'] ) ) { $error->add( $token['error']['code'], $token['error']['message'], array( $token['error']['status'], 'trying to exchange access code for token' ) ); } else if ( isset( $token['error'] ) && isset( $token['error_description'] ) ) { $error->add( $token['error'], $token['error_description'], 'trying to exchange access code for token' ); } else if ( isset( $token['error']['code'] ) && isset( $token['error']['message'] ) ) { $error->add( $token['error']['code'], $token['error']['message'], 'trying to verify site' ); } AIWP_Tools::set_error( $error, $timeout ); return false; } if ( isset( $token['access_token'] ) ) { return $token; } else { return false; } } /** * Handles the token refresh process * @return string|number|boolean */ public function refresh_token() { $token = (array) $this->aiwp->config->options['token']; $refresh_token = $token['refresh_token']; $challenge = ( isset( $token['challenge'] ) && '' != $token['challenge'] ) ? $token['challenge'] : ''; if ( ! $token || ! isset( $token['expires_in'] ) || ( $token['created'] + ( $token['expires_in'] - 30 ) ) < time() ) { // @formatter:off $post_data = array( 'client_id' => $this->client_id, 'client_secret' => $this->aiwp->config->options['user_api'] ? $this->client_secret : $this->client_secret . '-' . $challenge, 'refresh_token' => $refresh_token, 'grant_type' => 'refresh_token' ); // @formatter:on $request_args = array( 'body' => $post_data, 'headers' => array( 'Referer' => AIWP_CURRENT_VERSION ) ); if ( $this->aiwp->config->options['user_api'] ) { $token_uri = 'https://oauth2.googleapis.com/token'; } else { $token_uri = $challenge ? 'https://oauth2.googleapis.com/token' : AIWP_ENDPOINT_URL . 'aiwp-token.php'; } $response = wp_remote_post( $token_uri, $request_args ); if ( is_wp_error( $response ) ) { $timeout = $this->get_timeouts(); AIWP_Tools::set_error( $response, $timeout ); } else { $body = wp_remote_retrieve_body( $response ); if ( is_string( $body ) && ! empty( $body ) ) { $newtoken = json_decode( $body, true ); if ( isset( $newtoken['error'] ) ) { $timeout = $this->get_timeouts(); $error = new WP_Error(); if ( isset( $newtoken['error']['code'] ) && isset( $newtoken['error']['status'] ) ) { $error->add( $newtoken['error']['code'], $newtoken['error']['message'], array( $newtoken['error']['status'], 'trying to refresh token' ) ); } else if ( isset( $newtoken['error'] ) && isset( $newtoken['error_description'] ) ) { $error->add( $newtoken['error'], $newtoken['error_description'], 'trying to refresh token' ); } else if ( isset( $newtoken['error']['code'] ) && isset( $newtoken['error']['message'] ) ) { $error->add( $newtoken['error']['code'], $newtoken['error']['message'], 'trying to verify site' ); } AIWP_Tools::set_error( $error, $timeout ); return false; } if ( ! empty( $newtoken ) && isset( $newtoken['access_token'] ) ) { if ( ! isset( $newtoken['created'] ) ) { $newtoken['created'] = time(); } if ( ! isset( $newtoken['refresh_token'] ) ) { $newtoken['refresh_token'] = $refresh_token; } if ( ! isset( $newtoken['challenge'] ) && '' != $challenge ) { $newtoken['challenge'] = $challenge; } $this->aiwp->config->options['token'] = $newtoken; } else { $this->aiwp->config->options['token'] = false; } } else { $this->aiwp->config->options['token'] = false; } if ( is_multisite() && $this->aiwp->config->options['network_mode'] ) { $this->aiwp->config->set_plugin_options( true ); } else { $this->aiwp->config->set_plugin_options(); } } } if ( $this->aiwp->config->options['token'] ) { return true; } else { return false; } } /** * Handles the token reset process * * @param * $all */ public function reset_token( $all = false, $valid_token = true ) { if ( $all ) { $this->aiwp->config->options['ga4_webstreams_list'] = array(); $this->aiwp->config->options['webstream_jail'] = ''; } $this->aiwp->config->options['token'] = false; if ( is_multisite() && $this->aiwp->config->options['network_mode'] ) { $this->aiwp->config->set_plugin_options( true ); } else { $this->aiwp->config->set_plugin_options(); } } /** * Handles the token revoke process * * @param * $all */ public function revoke_token( $all = false, $valid_token = true ) { // See notes don't use unless mandatory $token = (array) $this->aiwp->config->options['token']; if ( isset( $token['refresh_token'] ) && $valid_token ) { // @formatter:off $post_data = array( 'token' => $token['refresh_token'], ); // @formatter:on $request_args = array( 'body' => $post_data, 'headers' => array( 'Referer' => AIWP_CURRENT_VERSION ) ); $response = wp_remote_post( $this->revoke_uri, $request_args ); } } /** * Handles errors returned by GAPI Library * * @return boolean */ public function api_errors_handler() { $errors = AIWP_Tools::get_cache( 'api_errors' ); // Proceed as normal if we don't know the error if ( false === $errors || ! isset( $errors[0] ) ) { return false; } // Reset the token since these are unrecoverable errors and need user intervention // We can also add 'INVALID_ARGUMENT' if ( isset( $errors[2][0] ) && ( 'INVALID_ARGUMENTS' == $errors[2][0] || 'UNAUTHENTICATED' == $errors[2][0] || 'PERMISSION_DENIED' == $errors[2][0] ) ) { $this->reset_token( false, false ); return $errors[0]; } // Reset the token since these are unrecoverable errors and need user intervention // We can also add 'invalid_grant' if ( isset( $errors[0] ) && ( 'invalid_grant' == $errors[0] || 'invalid_token' == $errors[0] ) ) { $this->reset_token( false, false ); return $errors[0]; } if ( 401 == $errors[0] || 403 == $errors[0] ) { return $errors[0]; } // Back-off processing until the error timeouts, usually at midnight if ( isset( $errors[1][0]['reason'] ) && ( 'dailyLimitExceeded' == $errors[1][0]['reason'] || 'userRateLimitExceeded' == $errors[1][0]['reason'] || 'rateLimitExceeded' == $errors[1][0]['reason'] || 'quotaExceeded' == $errors[1][0]['reason'] ) ) { return $errors[0]; } // Back-off system for subsequent requests - an Auth error generated after a Service request if ( isset( $errors[1][0]['reason'] ) && ( 'authError' == $errors[1][0]['reason'] ) ) { if ( $this->aiwp->config->options['api_backoff'] <= 5 ) { usleep( $this->aiwp->config->options['api_backoff'] * 1000000 + rand( 100000, 1000000 ) ); $this->aiwp->config->options['api_backoff'] = $this->aiwp->config->options['api_backoff'] + 1; $this->aiwp->config->set_plugin_options(); return false; } else { return $errors[0]; } } if ( 500 == $errors[0] || 503 == $errors[0] ) { return $errors[0]; } return false; } /** * Calculates proper timeouts for each GAPI query * * @param * $interval * @return number */ public function get_timeouts( $interval = '' ) { $local_time = time() + $this->timeshift; if ( 'daily' == $interval ) { $nextday = explode( '-', date( 'n-j-Y', strtotime( ' +1 day', $local_time ) ) ); $midnight = mktime( 0, 0, 0, $nextday[0], $nextday[1], $nextday[2] ); return $midnight - $local_time; } else if ( 'midnight' == $interval ) { $midnight = strtotime( "tomorrow 00:00:00" ); // UTC midnight $midnight = $midnight + 8 * 3600; // UTC 8 AM return $midnight - time(); } else if ( 'hourly' == $interval ) { $nexthour = explode( '-', date( 'H-n-j-Y', strtotime( ' +1 hour', $local_time ) ) ); $newhour = mktime( $nexthour[0], 0, 0, $nexthour[1], $nexthour[2], $nexthour[3] ); return $newhour - $local_time; } else { return 0; } } /** * Retrieves all Google Analytics 4 Properties with details * * @return array */ public function refresh_profiles_ga4() { $token = (array) $this->aiwp->config->options['token']; $access_token = $token['access_token']; $pageSize = 100; // @formatter:off $headers = array( 'Authorization' => 'Bearer ' . $access_token, 'Content-Type' => 'application/json' ); // @formatter:on $accountPageToken = null; do { $accountsEndpoint = "https://analyticsadmin.googleapis.com/v1beta/accounts?pageSize={$pageSize}"; if ( $accountPageToken ) { $accountsEndpoint .= "&pageToken={$accountPageToken}"; } $accountsResponse = wp_remote_get( $accountsEndpoint, array( 'headers' => $headers ) ); if ( is_wp_error( $accountsResponse ) ) { $timeout = $this->get_timeouts(); AIWP_Tools::set_error( $accountsResponse, $timeout ); return $accountsResponse->get_error_code(); } else { $accountsBody = wp_remote_retrieve_body( $accountsResponse ); $accountsData = json_decode( $accountsBody, true ); if ( isset( $accountsData['error'] ) ) { $timeout = $this->get_timeouts(); $error = new WP_Error(); if ( isset( $accountsData['error']['code'] ) && isset( $accountsData['error']['status'] ) ) { $error->add( $accountsData['error']['code'], $accountsData['error']['message'], array( $accountsData['error']['status'], 'trying to refresh token' ) ); } else if ( isset( $accountsData['error'] ) && isset( $accountsData['error_description'] ) ) { $error->add( $accountsData['error'], $accountsData['error_description'], 'trying to refresh token' ); } else if ( isset( $accountsData['error']['code'] ) && isset( $accountsData['error']['message'] ) ) { $error->add( $accountsData['error']['code'], $accountsData['error']['message'], 'trying to verify site' ); } AIWP_Tools::set_error( $error, $timeout ); return $error->get_error_code(); } if ( isset( $accountsData['accounts'] ) ) { foreach ( $accountsData['accounts'] as $account ) { $propertyPageToken = null; do { $propertiesEndpoint = "https://analyticsadmin.googleapis.com/v1beta/properties?filter=parent:{$account['name']}&pageSize={$pageSize}"; if ( $propertyPageToken ) { $propertiesEndpoint .= "&pageToken={$propertyPageToken}"; } $propertiesResponse = wp_remote_get( $propertiesEndpoint, array( 'headers' => $headers ) ); if ( is_wp_error( $propertiesResponse ) ) { $timeout = $this->get_timeouts(); AIWP_Tools::set_error( $propertiesResponse, $timeout ); return $propertiesResponse->get_error_code(); } else { $propertiesBody = wp_remote_retrieve_body( $propertiesResponse ); $propertiesData = json_decode( $propertiesBody, true ); if ( isset( $propertiesData['error'] ) ) { $timeout = $this->get_timeouts(); $error = new WP_Error(); if ( isset( $propertiesData['error']['code'] ) && isset( $propertiesData['error']['status'] ) ) { $error->add( $propertiesData['error']['code'], $propertiesData['error']['message'], array( $propertiesData['error']['status'], 'trying to refresh token' ) ); } else if ( isset( $propertiesData['error'] ) && isset( $propertiesData['error_description'] ) ) { $error->add( $propertiesData['error'], $propertiesData['error_description'], 'trying to refresh token' ); } else if ( isset( $propertiesData['error']['code'] ) && isset( $propertiesData['error']['message'] ) ) { $error->add( $propertiesData['error']['code'], $propertiesData['error']['message'], 'trying to verify site' ); } AIWP_Tools::set_error( $error, $timeout ); return $error->get_error_code(); } if ( isset( $propertiesData['properties'] ) ) { foreach ( $propertiesData['properties'] as $property ) { $datastreamsPageToken = null; do { $datastreamsEndpoint = "https://analyticsadmin.googleapis.com/v1beta/{$property['name']}/dataStreams?pageSize={$pageSize}"; if ( $datastreamsPageToken ) { $datastreamsEndpoint .= "&pageToken={$datastreamsPageToken}"; } $datastreamsResponse = wp_remote_get( $datastreamsEndpoint, array( 'headers' => $headers ) ); if ( is_wp_error( $datastreamsResponse ) ) { $timeout = $this->get_timeouts(); AIWP_Tools::set_error( $datastreamsResponse, $timeout ); return $datastreamsResponse->get_error_code(); } else { $datastreamsBody = wp_remote_retrieve_body( $datastreamsResponse ); $datastreamsData = json_decode( $datastreamsBody, true ); if ( isset( $datastreamsData['error'] ) ) { $timeout = $this->get_timeouts(); $error = new WP_Error(); if ( isset( $datastreamsData['error']['code'] ) && isset( $datastreamsData['error']['status'] ) ) { $error->add( $datastreamsData['error']['code'], $datastreamsData['error']['message'], array( $datastreamsData['error']['status'], 'trying to refresh token' ) ); } else if ( isset( $datastreamsData['error'] ) && isset( $datastreamsData['error_description'] ) ) { $error->add( $datastreamsData['error'], $datastreamsData['error_description'], 'trying to refresh token' ); } else if ( isset( $datastreamsData['error']['code'] ) && isset( $datastreamsData['error']['message'] ) ) { $error->add( $datastreamsData['error']['code'], $datastreamsData['error']['message'], 'trying to verify site' ); } AIWP_Tools::set_error( $error, $timeout ); return $error->get_error_code(); } if ( isset( $datastreamsData['dataStreams'] ) ) { foreach ( $datastreamsData['dataStreams'] as $datastream ) { if ( 'WEB_DATA_STREAM' == $datastream['type'] ) { $timetz = new DateTimeZone( $property['timeZone'] ); $localtime = new DateTime( 'now', $timetz ); $timeshift = strtotime( $localtime->format( 'Y-m-d H:i:s' ) ) - time(); $ga4_webstreams_list[] = array( $datastream['displayName'], $datastream['name'], $datastream['webStreamData']['defaultUri'], $datastream['webStreamData']['measurementId'], $timeshift, $property['timeZone'] ); } } $datastreamsPageToken = isset( $datastreamsData['nextPageToken'] ) ? $datastreamsData['nextPageToken'] : null; } } } while ( $datastreamsPageToken ); } } $propertyPageToken = isset( $propertiesData['nextPageToken'] ) ? $propertiesData['nextPageToken'] : null; } } while ( $propertyPageToken ); } } $accountPageToken = isset( $accountsData['nextPageToken'] ) ? $accountsData['nextPageToken'] : null; } } while ( $accountPageToken ); return $ga4_webstreams_list; } /** * Generates serials for transients * * @param * $serial * @return string */ public function get_serial( $serial ) { return sprintf( "%u", crc32( $serial ) ); } /** * Google Analtyics 4 Reports Get and cache * * @param * $projecId * @param * $from * @param * $to * @param * $metrics * @param * $options * @param * $serial * @return int */ private function handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, $sortby, $filters, $serial ) { if ( 'today' == $from ) { $interval = 'hourly'; } else { $interval = 'daily'; } $transient = AIWP_Tools::get_cache( $serial ); if ( false === $transient ) { if ( $this->api_errors_handler() ) { return $this->api_errors_handler(); } $projectIdArr = explode( '/dataStreams/', $projectId ); $projectId = $projectIdArr[0]; $api_url = 'https://analyticsdata.googleapis.com/v1beta/' . $projectId . ':runReport'; $quotauser = $this->get_serial( $this->quotauser . $projectId ); $api_url = $api_url . '?quotaUser=' . $quotauser; $token = (array) $this->aiwp->config->options['token']; if ( isset( $token['access_token'] ) ) { $access_token = $token['access_token']; } else { return 624; } // @formatter:off $headers = array( 'Authorization' => 'Bearer ' . $access_token, 'Content-Type' => 'application/json', ); // @formatter:on $request_body = array( 'dateRanges' => array( 'startDate' => $from, 'endDate' => $to ) ); if ( is_array( $metrics ) ) { $request_body['metrics'] = array(); foreach ( $metrics as $metric ) { $metric = AIWP_Tools::ga3_ga4_mapping( $metric ); $request_body['metrics'][] = array( 'name' => $metric ); } } else { $metric = AIWP_Tools::ga3_ga4_mapping( $metrics ); $request_body['metrics'] = array(); $request_body['metrics'][] = array( 'name' => $metric ); } $request_body['metricAggregations'] = 'TOTAL'; $request_body['keepEmptyRows'] = 'true'; if ( $dimensions ) { if ( is_array( $dimensions ) ) { $request_body['dimensions'] = array(); foreach ( $dimensions as $dimension ) { $dimension = AIWP_Tools::ga3_ga4_mapping( $dimension ); $request_body['dimensions'][] = array( 'name' => $dimension ); } } else { $dimension = AIWP_Tools::ga3_ga4_mapping( $dimensions ); $request_body['dimensions'] = array(); $request_body['dimensions'][] = array( 'name' => $dimension ); } } if ( $filters ) { if ( count( $filters ) === 1 ) { $filter = $filters[0]; $filter[0] = AIWP_Tools::ga3_ga4_mapping( $filter[0] ); $fieldName = $filter[0]; $filterMatch = $filter[1]; $filterValue = $filter[2]; $filterData = array( 'fieldName' => $fieldName, 'stringFilter' => array( 'matchType' => $filterMatch, 'value' => $filterValue ) ); if ( $filter[3] ) { $request_body['dimensionFilter']['notExpression']['filter'] = $filterData; } else { $request_body['dimensionFilter']['filter'] = $filterData; } } else { $filterExpressions = array(); foreach ( $filters as $filter ) { $filter[0] = AIWP_Tools::ga3_ga4_mapping( $filter[0] ); $fieldName = $filter[0]; $filterMatch = $filter[1]; $filterValue = $filter[2]; $filterData = array( 'fieldName' => $fieldName, 'stringFilter' => array( 'matchType' => $filterMatch, 'value' => $filterValue ) ); if ( $filter[3] ) { $notExpression = array(); $notExpression['notExpression'] = array( 'filter' => $filterData ); $filterExpressions[] = $notExpression; } else { $filterExpressions[] = array( 'filter' => $filterData ); } $request_body['dimensionFilter']['andGroup'] = array( 'expressions' => $filterExpressions ); } } } if ( $sortby ) { $metric = AIWP_Tools::ga3_ga4_mapping( $metrics ); $metricName = $metric; $desc = true; $orderCriteria = array( 'metricName' => $metricName ); $request_body['orderBys']['metric'] = $orderCriteria; $request_body['orderBys']['desc'] = $desc; } else { if ( is_array( $dimensions ) ) { $dimension = AIWP_Tools::ga3_ga4_mapping( $dimensions[0] ); $dimensionName = $dimension; $orderType = 'NUMERIC'; $desc = false; $orderCriteria = array( 'dimensionName' => $dimensionName, 'orderType' => $orderType ); $request_body['orderBys']['dimension'] = $orderCriteria; $request_body['orderBys']['desc'] = $desc; } } $request_body_json = json_encode( $request_body ); $args = array( 'headers' => $headers, 'body' => $request_body_json ); $response = wp_remote_post( $api_url, $args ); if ( is_wp_error( $response ) ) { $timeout = $this->get_timeouts(); AIWP_Tools::set_error( $response, $timeout ); return $response->get_error_code(); } else { $response_body = wp_remote_retrieve_body( $response ); $response_data = json_decode( $response_body, true ); if ( isset( $response_data['error'] ) ) { $timeout = $this->get_timeouts(); $error = new WP_Error(); if ( isset( $response_data['error']['code'] ) && isset( $response_data['error']['status'] ) ) { $error->add( $response_data['error']['code'], $response_data['error']['message'], array( $response_data['error']['status'], 'trying to refresh token' ) ); } else if ( isset( $response_data['error'] ) && isset( $response_data['error_description'] ) ) { $error->add( $response_data['error'], $response_data['error_description'], 'trying to refresh token' ); } else if ( isset( $response_data['error']['code'] ) && isset( $response_data['error']['message'] ) ) { $error->add( $response_data['error']['code'], $response_data['error']['message'], 'trying to verify site' ); } AIWP_Tools::set_error( $error, $timeout ); return $error->get_error_code(); } if ( isset( $response_data['rows'] ) ) { $data['values'] = array(); foreach ( $response_data['rows'] as $row ) { $values = array(); if ( isset( $row['dimensionValues'][0] ) ) { foreach ( $row['dimensionValues'] as $item ) { $values[] = $item['value']; } } if ( isset( $row['metricValues'][0] ) ) { foreach ( $row['metricValues'] as $item ) { $values[] = $item['value']; } } $data['values'][] = $values; } $data['totals'] = 0; if ( isset( $response_data['totals'][0]['metricValues'][0]['value'] ) ) { $data['totals'] = $response_data['totals'][0]['metricValues'][0]['value']; } AIWP_Tools::set_cache( $serial, $data, $this->get_timeouts( $interval ) ); } else { return 621; } } } else { $data = $transient; } $this->aiwp->config->options['api_backoff'] = 0; $this->aiwp->config->set_plugin_options(); return $data; } /** * Google Analytics 4 data for Area Charts (Admin Dashboard Widget report) * * @param * $projectId * @param * $from * @param * $to * @param * $query * @param * $filter * @return array|int */ private function get_areachart_data_ga4( $projectId, $from, $to, $query, $filter = '' ) { $factor = 1; switch ( $query ) { case 'users' : $title = __( "Users", 'analytics-insights' ); break; case 'pageviews' : $title = __( "Page Views", 'analytics-insights' ); break; case 'visitBounceRate' : $title = __( "Bounce Rate", 'analytics-insights' ); $factor = 100; break; case 'organicSearches' : $title = __( "Engagement", 'analytics-insights' ); break; case 'uniquePageviews' : $title = __( "Unique Page Views", 'analytics-insights' ); break; default : $title = __( "Sessions", 'analytics-insights' ); } $metrics = 'ga:' . $query; if ( 'today' == $from || 'yesterday' == $from ) { $dimensions = 'ga:hour'; $dayorhour = __( "Hour", 'analytics-insights' ); } else if ( '365daysAgo' == $from || '1095daysAgo' == $from ) { $dimensions = array( 'ga:year', 'ga:month' ); $dayorhour = __( "Date", 'analytics-insights' ); } else { $dimensions = array( 'ga:date', 'ga:dayOfWeekName' ); $dayorhour = __( "Date", 'analytics-insights' ); } if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); } else { $filters = false; } $serial = 'qr2_' . $this->get_serial( $projectId . $from . $metrics . $filter ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, false, $filters, $serial ); if ( is_numeric( $data ) ) { return $data; } if ( isset( $data['values'] ) && empty( $data['values'] ) ) { return 621; } $aiwp_data = array( array( $dayorhour, $title ) ); if ( 'today' == $from || 'yesterday' == $from ) { for ( $i = 0; $i < 24; $i++ ) { $fill_data[$i] = 0; } foreach ( $data['values'] as $row ) { if ( array_key_exists( (int) $row[0], $fill_data ) ) { $fill_data[(int) $row[0]] = round( $row[1], 2 ) * $factor; } } foreach ( $fill_data as $key => $value ) { $aiwp_data[] = array( $key . ':00', $value ); } } else if ( '365daysAgo' == $from || '1095daysAgo' == $from ) { $yesterday = date( "Y-m-d", strtotime( "now" ) ); $offset = str_replace( 'daysAgo', '', $from ); $xdaysago = date( "Y-m-d", strtotime( "-" . $offset . " day" ) ); $period = new DatePeriod( new DateTime( $xdaysago ), new DateInterval( 'P1M' ), new DateTime( $yesterday ) ); foreach ( $period as $key => $value ) { $fill_data[$value->format( 'Ym' )] = 0; } foreach ( $data['values'] as $row ) { $key = $row[0] . $row[1]; if ( array_key_exists( $key, $fill_data ) ) { $fill_data[$key] = round( $row[2], 2 ) * $factor; } } foreach ( $fill_data as $key => $value ) { /* * translators: * Example: 'F, Y' will become 'November, 2015' * For details see: https://php.net/manual/en/function.date.php#refsect1-function.date-parameters */ $aiwp_data[] = array( date_i18n( __( 'F, Y', 'analytics-insights' ), strtotime( $key . '01' ) ), $value ); } } else { $yesterday = date( "Y-m-d", strtotime( "now" ) ); $offset = str_replace( 'daysAgo', '', $from ); $xdaysago = date( "Y-m-d", strtotime( "-" . $offset . " day" ) ); $period = new DatePeriod( new DateTime( $xdaysago ), new DateInterval( 'P1D' ), new DateTime( $yesterday ) ); foreach ( $period as $key => $value ) { $fill_data[$value->format( 'Ymd' )] = 0; } foreach ( $data['values'] as $row ) { if ( array_key_exists( $row[0], $fill_data ) ) { $fill_data[$row[0]] = round( $row[2], 2 ) * $factor; } } foreach ( $fill_data as $key => $value ) { /* * translators: * Example: 'l, F j, Y' will become 'Thusday, November 17, 2015' * For details see: https://php.net/manual/en/function.date.php#refsect1-function.date-parameters */ $aiwp_data[] = array( date_i18n( __( 'l, F j, Y', 'analytics-insights' ), strtotime( $key ) ), $value ); } } return $aiwp_data; } /** * Google Analytics 4 data for Bottom Stats (bottom stats on main report) * * @param * $projectId * @param * $from * @param * $to * @param * $filter * @return array|int */ private function get_bottomstats_ga4( $projectId, $from, $to, $filter = '' ) { if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); // @formatter:off $metrics = array( 'ga:sessions', 'ga:users', 'ga:pageviews', 'ga:BounceRate', 'averageSessionDuration', 'ga:pageviewsPerSession', 'engagedSessions', 'userEngagementDuration', ); // @formatter:on } else { $filters = false; // @formatter:off $metrics = array( 'ga:sessions', 'ga:users', 'ga:pageviews', 'ga:BounceRate', 'averageSessionDuration', 'ga:pageviewsPerSession', 'engagedSessions', 'userEngagementDuration', ); // @formatter:on } $sortby = false; $serial = 'qr30_' . $this->get_serial( $projectId . $from . $filter ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, false, $sortby, $filters, $serial ); if ( is_numeric( $data ) ) { return $data; } $aiwp_data = array(); $aiwp_data = $data['values'][0]; // i18n support $aiwp_data[0] = isset( $aiwp_data[0] ) ? number_format_i18n( $aiwp_data[0] ) : 0; $aiwp_data[1] = isset( $aiwp_data[1] ) ? number_format_i18n( $aiwp_data[1] ) : 0; $aiwp_data[2] = isset( $aiwp_data[2] ) ? number_format_i18n( $aiwp_data[2] ) : 0; $aiwp_data[3] = isset( $aiwp_data[3] ) ? number_format_i18n( $aiwp_data[3] * 100, 2 ) . '%' : '0%'; $aiwp_data[4] = isset( $aiwp_data[4] ) ? AIWP_Tools::secondstohms( $aiwp_data[4] ) : '00:00:00'; $aiwp_data[5] = isset( $aiwp_data[5] ) ? number_format_i18n( $aiwp_data[5], 2 ) : 0; $aiwp_data[6] = isset( $aiwp_data[6] ) ? number_format_i18n( $aiwp_data[6] ) : 0; ; $aiwp_data[7] = isset( $aiwp_data[7] ) ? AIWP_Tools::secondstohms( $aiwp_data[7] ) : '00:00:00'; // Get Organic Searches $metrics = 'ga:sessions'; $dimensions = 'ga:' . 'channelGrouping'; $sortby = '-' . $metrics; if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); } else { $filters = false; } $serial = 'qr9_' . $this->get_serial( $projectId . $from . 'channelGrouping' . $filter . 'ga:sessions' ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, $sortby, $filters, $serial ); $organic = 0; if ( isset( $data['values'] ) && !empty( $data['values'] ) ) { foreach ( $data['values'] as $row ) { if ( 'Organic Search' == $row[0] ) { $organic = number_format_i18n( $row[1] ); } } } array_splice( $aiwp_data, 6, 0, $organic ); return $aiwp_data; } /** * Google Analytics 4 data for Table Charts (location reports) * * @param * $projectId * @param * $from * @param * $to * @param * $filter * @return array|int */ private function get_locations_ga4( $projectId, $from, $to, $metric, $filter = '' ) { $metrics = 'ga:' . $metric; $title = __( "Countries", 'analytics-insights' ); $dimensions = 'ga:country'; $serial = 'qr7_' . $this->get_serial( $projectId . $from . $filter . $metric . $dimensions ); $local_filter = ''; if ( 'None' !== $this->aiwp->config->options['ga_target_geomap'] ) { $dimensions = array( 'ga:city', 'ga:region' ); if ( 'None' !== $this->aiwp->config->options['ga_target_geomap'] ) { $local_filter = array( 'ga:country', 'EXACT', ( $this->aiwp->config->options['ga_target_geomap'] ), false ); $title = __( "Cities from", 'analytics-insights' ) . ' ' . __( $this->aiwp->config->options['ga_target_geomap'] ); $serial = 'qr7_' . $this->get_serial( $projectId . $from . $this->aiwp->config->options['ga_target_geomap'] . $filter . $metric ); } } $sortby = '-' . $metrics; if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); if ( $local_filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); $filters[1] = $local_filter; } } else { if ( $local_filter ) { $filters[] = $local_filter; } } if ( '' === $filter && '' === $local_filter ) { $filters = false; } $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, $sortby, $filters, $serial ); if ( is_numeric( $data ) ) { return $data; } if ( isset( $data['values'] ) && empty( $data['values'] ) ) { return 621; } $aiwp_data = array( array( $title, __( ucfirst( $metric ), 'analytics-insights' ) ) ); foreach ( $data['values'] as $row ) { if ( isset( $row[2] ) ) { $aiwp_data[] = array( esc_html( $row[0] ) . ', ' . esc_html( $row[1] ), (int) $row[2] ); } else { $aiwp_data[] = array( esc_html( $row[0] ), (int) $row[1] ); } } return $aiwp_data; } /** * Google Analytics 4 data for Table Charts (content pages) * * @param * $projectId * @param * $from * @param * $to * @param * $filter * @return array|int */ private function get_contentpages_ga4( $projectId, $from, $to, $metric, $filter = '' ) { $metrics = 'ga:' . $metric; $dimensions = 'ga:pageTitle'; $sortby = '-' . $metrics; if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); } else { $filters = false; } $serial = 'qr4_' . $this->get_serial( $projectId . $from . $filter . $metric ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, $sortby, $filters, $serial ); if ( is_numeric( $data ) ) { return $data; } if ( isset( $data['values'] ) && empty( $data['values'] ) ) { return 621; } $aiwp_data = array( array( __( "Pages", 'analytics-insights' ), __( ucfirst( $metric ), 'analytics-insights' ) ) ); foreach ( $data['values'] as $row ) { $aiwp_data[] = array( esc_html( $row[0] ), (int) $row[1] ); } return $aiwp_data; } /** * Google Analytics 4 data for Org Charts (traffic channels, device categories) * * @param * $projectId * @param * $from * @param * $to * @param * $query * @param * $filter * @return array|int */ private function get_orgchart_data_ga4( $projectId, $from, $to, $query, $metric, $filter = '' ) { $metrics = 'ga:' . $metric; $dimensions = 'ga:' . $query; $sortby = '-' . $metrics; if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); } else { $filters = false; } $serial = 'qr8_' . $this->get_serial( $projectId . $from . $query . $filter . $metric ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, $sortby, $filters, $serial ); if ( is_numeric( $data ) ) { return $data; } if ( isset( $data['values'] ) && empty( $data['values'] ) ) { return 621; } $block = ( 'channelGrouping' == $query ) ? __( "Channels", 'analytics-insights' ) : __( "Devices", 'analytics-insights' ); $aiwp_data = array( array( '
' . $block . '
' . (int) $data['totals'] . '
', "" ) ); foreach ( $data['values'] as $row ) { $shrink = explode( " ", $row[0] ); if ( isset( $shrink[1] ) ) { $shrink[0] = esc_html( $shrink[0] ) . '
' . esc_html( $shrink[1] ); } if ( 'Unassigned' !== $shrink[0] ) { $aiwp_data[] = array( '
' . $shrink[0] . '
' . (int) $row[1] . '
', '
' . $block . '
' . (int) $data['totals'] . '
' ); } } return $aiwp_data; } /** * Google Analytics 4 data for Table Charts (referrers) * * @param * $projectId * @param * $from * @param * $to * @param * $filter * @return array|int */ private function get_referrers_ga4( $projectId, $from, $to, $metric, $filter = '' ) { $metrics = 'ga:' . $metric; $dimensions = 'ga:source'; $sortby = '-' . $metrics; if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); $filters[] = array( 'ga:medium', 'EXACT', 'referral', false ); } else { $filters[] = array( 'ga:medium', 'EXACT', 'referral', false ); } $serial = 'qr5_' . $this->get_serial( $projectId . $from . $filter . $metric ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, $sortby, $filters, $serial ); if ( is_numeric( $data ) ) { return $data; } if ( isset( $data['values'] ) && empty( $data['values'] ) ) { return 621; } $aiwp_data = array( array( __( "Referrers", 'analytics-insights' ), __( ucfirst( $metric ), 'analytics-insights' ) ) ); foreach ( $data['values'] as $row ) { $aiwp_data[] = array( esc_html( $row[0] ), (int) $row[1] ); } return $aiwp_data; } /** * Google Analytics 4 data for Table Charts (searches) * * @param * $projectId * @param * $from * @param * $to * @param * $filter * @return array|int */ private function get_searches_ga4( $projectId, $from, $to, $metric, $filter = '' ) { $metrics = 'ga:' . $metric; $dimensions = 'ga:source'; $sortby = '-' . $metrics; if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); $filters[] = array( 'ga:medium', 'EXACT', 'organic', false ); } else { $filters[] = array( 'ga:medium', 'EXACT', 'organic', false ); } $serial = 'qr6_' . $this->get_serial( $projectId . $from . $filter . $metric ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, $sortby, $filters, $serial ); if ( is_numeric( $data ) ) { return $data; } if ( isset( $data['values'] ) && empty( $data['values'] ) ) { return 621; } $aiwp_data = array( array( __( "Search Engines", 'analytics-insights' ), __( ucfirst( $metric ), 'analytics-insights' ) ) ); foreach ( $data['values'] as $row ) { $aiwp_data[] = array( esc_html( $row[0] ), (int) $row[1] ); } return $aiwp_data; } /** * Google Analytics 4 data for Pie Charts (traffic mediums, serach engines, languages, browsers, screen rsolutions, etc.) * * @param * $projectId * @param * $from * @param * $to * @param * $query * @param * $filter * @return array|int */ private function get_piechart_data_ga4( $projectId, $from, $to, $query, $metric, $filter = '' ) { $metrics = 'ga:' . $metric; $dimensions = 'ga:' . $query; $sortby = false; if ( 'source' == $query ) { $sortby = '-' . $metrics; if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); $filters[] = array( 'ga:medium', 'EXACT', 'organic', false ); } else { $filters[] = array( 'ga:medium', 'EXACT', 'organic', false ); } } else { $sortby = '-' . $metrics; if ( $filter ) { $filters[] = array( 'ga:pagePath', 'EXACT', $filter, false ); $filters[] = array( 'ga:' . $query, 'EXACT', '(not set)', true ); } else { $filters[] = array( 'ga:' . $query, 'EXACT', '(not set)', true ); } } $serial = 'qr10_' . $this->get_serial( $projectId . $from . $query . $filter . $metric ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, $sortby, $filters, $serial ); if ( is_numeric( $data ) ) { return $data; } if ( isset( $data['values'] ) && empty( $data['values'] ) ) { return 621; } $aiwp_data = array( array( __( "Type", 'analytics-insights' ), __( ucfirst( $metric ), 'analytics-insights' ) ) ); $included = 0; foreach ( $data['values'] as $row ) { $aiwp_data[] = array( str_replace( "(none)", "direct", esc_html( $row[0] ) ), (int) $row[1] ); $included += $row[1]; } $totals = $data['totals']; $others = $totals - $included; if ( $others > 0 ) { $aiwp_data[] = array( __( 'Other', 'analytics-insights' ), $others ); } return $aiwp_data; } /** * Google Analytics 4 data for 404 Errors * * @param * $projectId * @param * $from * @param * $to * @return array|int */ private function get_404errors_ga4( $projectId, $from, $to, $metric, $filter = "Page Not Found" ) { $metrics = 'ga:' . $metric; $dimensions = array( 'ga:pagePath', 'ga:fullReferrer', 'ga:pageTitle' ); $sortby = '-' . $metrics; $filters[] = array( 'ga:pageTitle', 'CONTAINS', $filter, false ); $serial = 'qr4_' . $this->get_serial( $projectId . $from . $filter . $metric ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, $sortby, $filters, $serial ); if ( is_numeric( $data ) ) { return $data; } if ( isset( $data['values'] ) && empty( $data['values'] ) ) { return 621; } $aiwp_data = array( array( __( "404 Errors", 'analytics-insights' ), __( ucfirst( $metric ), 'analytics-insights' ) ) ); foreach ( $data['values'] as $row ) { $path = esc_html( $row[0] ); $source = esc_html( $row[1] ); $aiwp_data[] = array( "" . __( "URI:", 'analytics-insights' ) . " " . $path . "
" . __( "Source:", 'analytics-insights' ) . " " . $source, (int) $row[3] ); } return $aiwp_data; } /** * Google Analytics 4 data for Frontend Widget (chart data and totals) * * @param * $projectId * @param * $period * @param * $anonim * @return array|int */ public function frontend_widget_stats_ga4( $projectId, $from, $anonim ) { $to = 'yesterday'; $metrics = 'ga:sessions'; $dimensions = array( 'ga:date', 'ga:dayOfWeekName' ); $serial = 'qr2_' . $this->get_serial( $projectId . $from . $metrics ); $data = $this->handle_corereports_ga4( $projectId, $from, $to, $metrics, $dimensions, false, false, $serial ); if ( is_numeric( $data ) ) { return $data; } if ( isset( $data['values'] ) && empty( $data['values'] ) ) { return 621; } $aiwp_data = array( array( __( "Date", 'analytics-insights' ), __( "Sessions", 'analytics-insights' ) ) ); if ( $anonim ) { $max_array = array(); foreach ( $data['values'] as $row ) { $max_array[] = $row[2]; } $max = max( $max_array ) ? max( $max_array ) : 1; } foreach ( $data['values'] as $row ) { $aiwp_data[] = array( date_i18n( __( 'l, F j, Y', 'analytics-insights' ), strtotime( $row[0] ) ), ( $anonim ? round( $row[2] * 100 / $max, 2 ) : (int) $row[2] ) ); } $totals = $data['totals']; return array( $aiwp_data, $anonim ? 0 : number_format_i18n( $totals ) ); } /** * Google Analytics 4 data for Realtime component (the real-time report) * * @param * $projectId * @return array|int */ private function get_realtime_ga4( $projectId ) { $metrics = 'activeUsers'; $dimensions = array( 'unifiedScreenName' ); $dimensions1 = array( 'deviceCategory' ); $projectIdArr = explode( '/dataStreams/', $projectId ); $projectId = $projectIdArr[0]; $api_url = 'https://analyticsdata.googleapis.com/v1beta/' . $projectId . ':runRealtimeReport'; $quotauser = $this->get_serial( $this->quotauser . $projectId ); $api_url = $api_url . '?quotaUser=' . $quotauser; $serial = 'qr_realtimecache_' . $this->get_serial( $projectId ); $transient = AIWP_Tools::get_cache( $serial ); if ( false === $transient ) { if ( $this->api_errors_handler() ) { return $this->api_errors_handler(); } if ( is_array( $metrics ) ) { $request_body['metrics'] = array(); foreach ( $metrics as $metric ) { $metric = AIWP_Tools::ga3_ga4_mapping( $metric ); $request_body['metrics'][] = array( 'name' => $metric ); } } else { $metric = AIWP_Tools::ga3_ga4_mapping( $metrics ); $request_body['metrics'] = array(); $request_body['metrics'][] = array( 'name' => $metric ); } $request_body['metricAggregations'] = 'TOTAL'; if ( $dimensions ) { if ( is_array( $dimensions ) ) { $request_body['dimensions'] = array(); foreach ( $dimensions as $dimension ) { $dimension = AIWP_Tools::ga3_ga4_mapping( $dimension ); $request_body['dimensions'][] = array( 'name' => $dimension ); } } else { $dimension = AIWP_Tools::ga3_ga4_mapping( $dimensions ); $request_body['dimensions'] = array(); $request_body['dimensions'][] = array( 'name' => $dimension ); } } $token = (array) $this->aiwp->config->options['token']; if ( isset( $token['access_token'] ) ) { $access_token = $token['access_token']; } else { return 624; } // Get Page Data $headers = array( 'Authorization' => 'Bearer ' . $access_token, 'Content-Type' => 'application/json' ); $request_body_json = json_encode( $request_body ); $args = array( 'headers' => $headers, 'body' => $request_body_json ); $response = wp_remote_post( $api_url, $args ); if ( is_wp_error( $response ) ) { $timeout = $this->get_timeouts(); AIWP_Tools::set_error( $response, $timeout ); return $response->get_error_code(); } else { $response_body = wp_remote_retrieve_body( $response ); $response_data = json_decode( $response_body, true ); if ( isset( $response_data['error'] ) ) { $timeout = $this->get_timeouts(); $error = new WP_Error(); if ( isset( $response_data['error']['code'] ) && isset( $response_data['error']['status'] ) ) { $error->add( $response_data['error']['code'], $response_data['error']['message'], array( $response_data['error']['status'], 'trying to refresh token' ) ); } else if ( isset( $response_data['error'] ) && isset( $response_data['error_description'] ) ) { $error->add( $response_data['error'], $response_data['error_description'], 'trying to refresh token' ); } else if ( isset( $response_data['error']['code'] ) && isset( $response_data['error']['message'] ) ) { $error->add( $response_data['error']['code'], $response_data['error']['message'], 'trying to verify site' ); } AIWP_Tools::set_error( $error, $timeout ); return $error->get_error_code(); } $data = $response_data; } // Get Device Category Data if ( $dimensions1 ) { if ( is_array( $dimensions1 ) ) { $request_body['dimensions'] = array(); foreach ( $dimensions1 as $dimension ) { $dimension = AIWP_Tools::ga3_ga4_mapping( $dimension ); $request_body['dimensions'][] = array( 'name' => $dimension ); } } else { $dimension = AIWP_Tools::ga3_ga4_mapping( $dimensions1 ); $request_body['dimensions'] = array(); $request_body['dimensions'][] = array( 'name' => $dimension ); } } $headers = array( 'Authorization' => 'Bearer ' . $access_token, 'Content-Type' => 'application/json' ); $request_body_json = json_encode( $request_body ); $args = array( 'headers' => $headers, 'body' => $request_body_json ); $response = wp_remote_post( $api_url, $args ); if ( is_wp_error( $response ) ) { $timeout = $this->get_timeouts(); AIWP_Tools::set_error( $response, $timeout ); return $response->get_error_code(); } else { $response_body = wp_remote_retrieve_body( $response ); $response_data = json_decode( $response_body, true ); if ( isset( $response_data['error'] ) ) { $timeout = $this->get_timeouts(); $error = new WP_Error(); if ( isset( $response_data['error']['code'] ) && isset( $response_data['error']['status'] ) ) { $error->add( $response_data['error']['code'], $response_data['error']['message'], array( $response_data['error']['status'], 'trying to refresh token' ) ); } else if ( isset( $response_data['error'] ) && isset( $response_data['error_description'] ) ) { $error->add( $response_data['error'], $response_data['error_description'], 'trying to refresh token' ); } else if ( isset( $response_data['error']['code'] ) && isset( $response_data['error']['message'] ) ) { $error->add( $response_data['error']['code'], $response_data['error']['message'], 'trying to verify site' ); } AIWP_Tools::set_error( $error, $timeout ); return $error->get_error_code(); } $category = $response_data; } AIWP_Tools::set_cache( $serial, array( $data, $category ), 55 ); } else { $data = $transient[0]; $category = $transient[1]; } if ( ! isset( $data['rows'] ) ) { return 621; } if ( isset( $data['rows'] ) ) { $aiwp_data['rows'] = array(); foreach ( $data['rows'] as $row ) { $values = array(); if ( isset( $row['dimensionValues'][0] ) ) { foreach ( $row['dimensionValues'] as $item ) { $values[] = $item['value']; } } if ( isset( $row['metricValues'][0] ) ) { foreach ( $row['metricValues'] as $item ) { $values[] = $item['value']; } } $aiwp_data['rows'][] = $values; } } if ( isset( $category['rows'] ) ) { $aiwp_data['category'] = array(); foreach ( $category['rows'] as $row ) { $values = array(); if ( isset( $row['dimensionValues'][0] ) ) { foreach ( $row['dimensionValues'] as $item ) { $values[] = $item['value']; } } if ( isset( $row['metricValues'][0] ) ) { foreach ( $row['metricValues'] as $item ) { $values[] = $item['value']; } } $aiwp_data['category'][] = $values; } } // Leveraging total counts to JavaScript $aiwp_data['totals'] = 0; return $aiwp_data; } /** * Handles ajax requests and calls the needed methods * @param * $projectId * @param * $query * @param * $from * @param * $to * @param * $filter * @return number */ public function get( $projectId, $query, $from = false, $to = false, $filter = '', $metric = 'sessions' ) { if ( empty( $projectId ) || '' == $projectId || 'Disabled' == $projectId ) { wp_die( 626 ); } if ( in_array( $query, array( 'sessions', 'users', 'organicSearches', 'visitBounceRate', 'pageviews', 'uniquePageviews' ) ) ) { return $this->get_areachart_data_ga4( $projectId, $from, $to, $query, $filter ); } if ( 'bottomstats' == $query ) { return $this->get_bottomstats_ga4( $projectId, $from, $to, $filter ); } if ( 'locations' == $query ) { return $this->get_locations_ga4( $projectId, $from, $to, $metric, $filter ); } if ( 'contentpages' == $query ) { return $this->get_contentpages_ga4( $projectId, $from, $to, $metric, $filter ); } if ( 'referrers' == $query ) { return $this->get_referrers_ga4( $projectId, $from, $to, $metric, $filter ); } if ( 'searches' == $query ) { return $this->get_searches_ga4( $projectId, $from, $to, $metric, $filter ); } if ( '404errors' == $query ) { $filter = $this->aiwp->config->options['pagetitle_404']; return $this->get_404errors_ga4( $projectId, $from, $to, $metric, $filter ); } if ( 'realtime' == $query ) { return $this->get_realtime_ga4( $projectId ); } if ( 'channelGrouping' == $query || 'deviceCategory' == $query ) { return $this->get_orgchart_data_ga4( $projectId, $from, $to, $query, $metric, $filter ); } if ( in_array( $query, array( 'medium', 'visitorType', 'socialNetwork', 'source', 'browser', 'operatingSystem', 'screenResolution', 'mobileDeviceBranding' ) ) ) { return $this->get_piechart_data_ga4( $projectId, $from, $to, $query, $metric, $filter ); } wp_die( 627 ); } } }