update
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter\Filter
|
||||
*
|
||||
* @package Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter
|
||||
* @copyright 2023 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://sitekit.withgoogle.com
|
||||
*/
|
||||
|
||||
namespace Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter;
|
||||
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\FilterExpression as Google_Service_AnalyticsData_FilterExpression;
|
||||
|
||||
/**
|
||||
* Interface for a dimension filter class.
|
||||
*
|
||||
* @since 1.106.0
|
||||
*/
|
||||
interface Filter {
|
||||
|
||||
/**
|
||||
* Converts the dimension filter into the GA4 compatible dimension filter expression.
|
||||
*
|
||||
* @since 1.106.0
|
||||
*
|
||||
* @param string $dimension_name The dimension name.
|
||||
* @param mixed $dimension_value The dimension filter value.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression instance.
|
||||
*/
|
||||
public function parse_filter_expression( $dimension_name, $dimension_value );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter\In_List_Filter
|
||||
*
|
||||
* @package Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter
|
||||
* @copyright 2023 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://sitekit.withgoogle.com
|
||||
*/
|
||||
|
||||
namespace Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter;
|
||||
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\Filter as Google_Service_AnalyticsData_Filter;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\FilterExpression as Google_Service_AnalyticsData_FilterExpression;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\InListFilter as Google_Service_AnalyticsData_InListFilter;
|
||||
|
||||
/**
|
||||
* Class for parsing the dimension in-list filter.
|
||||
*
|
||||
* @since 1.106.0
|
||||
* @access private
|
||||
* @ignore
|
||||
*/
|
||||
class In_List_Filter implements Filter {
|
||||
|
||||
/**
|
||||
* Converts the dimension filter into the GA4 compatible dimension filter expression.
|
||||
*
|
||||
* @since 1.106.0
|
||||
*
|
||||
* @param string $dimension_name The dimension name.
|
||||
* @param mixed $dimension_value The dimension filter value.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression instance.
|
||||
*/
|
||||
public function parse_filter_expression( $dimension_name, $dimension_value ) {
|
||||
$in_list_filter = new Google_Service_AnalyticsData_InListFilter();
|
||||
$in_list_filter->setValues( $dimension_value );
|
||||
|
||||
$filter = new Google_Service_AnalyticsData_Filter();
|
||||
$filter->setFieldName( $dimension_name );
|
||||
$filter->setInListFilter( $in_list_filter );
|
||||
|
||||
$expression = new Google_Service_AnalyticsData_FilterExpression();
|
||||
$expression->setFilter( $filter );
|
||||
|
||||
return $expression;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter\String_Filter
|
||||
*
|
||||
* @package Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter
|
||||
* @copyright 2023 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://sitekit.withgoogle.com
|
||||
*/
|
||||
|
||||
namespace Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter;
|
||||
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\Filter as Google_Service_AnalyticsData_Filter;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\FilterExpression as Google_Service_AnalyticsData_FilterExpression;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\FilterExpressionList as Google_Service_AnalyticsData_FilterExpressionList;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\StringFilter as Google_Service_AnalyticsData_StringFilter;
|
||||
|
||||
/**
|
||||
* Class for parsing the dimension string filter.
|
||||
*
|
||||
* @since 1.106.0
|
||||
* @access private
|
||||
* @ignore
|
||||
*/
|
||||
class String_Filter implements Filter {
|
||||
|
||||
/**
|
||||
* Converts the dimension filter into the GA4 compatible dimension filter expression.
|
||||
*
|
||||
* @since 1.106.0
|
||||
*
|
||||
* @param string $dimension_name The dimension name.
|
||||
* @param mixed $dimension_value The dimension filter value.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression instance.
|
||||
*/
|
||||
public function parse_filter_expression( $dimension_name, $dimension_value ) {
|
||||
$match_type = isset( $dimension_value['matchType'] )
|
||||
? $dimension_value['matchType']
|
||||
: 'EXACT';
|
||||
|
||||
$filter_value = isset( $dimension_value['value'] )
|
||||
? $dimension_value['value']
|
||||
: $dimension_value;
|
||||
|
||||
// If there are many values for this filter, then it means that we want to find
|
||||
// rows where dimension are included in the list of provided values. In this case,
|
||||
// we need to create a nested filter expression that contains separate string filters
|
||||
// for each item in the list and combined into the "OR" group.
|
||||
if ( is_array( $filter_value ) ) {
|
||||
$expressions = array();
|
||||
foreach ( $filter_value as $value ) {
|
||||
$expressions[] = $this->compose_individual_filter_expression(
|
||||
$dimension_name,
|
||||
$match_type,
|
||||
$value
|
||||
);
|
||||
}
|
||||
|
||||
$expression_list = new Google_Service_AnalyticsData_FilterExpressionList();
|
||||
$expression_list->setExpressions( $expressions );
|
||||
|
||||
$filter_expression = new Google_Service_AnalyticsData_FilterExpression();
|
||||
$filter_expression->setOrGroup( $expression_list );
|
||||
|
||||
return $filter_expression;
|
||||
}
|
||||
|
||||
// If we have a single value for the filter, then we should use just a single
|
||||
// string filter expression and there is no need to create a nested one.
|
||||
return $this->compose_individual_filter_expression(
|
||||
$dimension_name,
|
||||
$match_type,
|
||||
$filter_value
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes individual filter expression and returns it.
|
||||
*
|
||||
* @since 1.106.0
|
||||
*
|
||||
* @param string $dimension_name The dimension name.
|
||||
* @param string $match_type The dimension filter match type.
|
||||
* @param mixed $value The dimension filter value.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression instance.
|
||||
*/
|
||||
protected function compose_individual_filter_expression( $dimension_name, $match_type, $value ) {
|
||||
$string_filter = new Google_Service_AnalyticsData_StringFilter();
|
||||
$string_filter->setMatchType( $match_type );
|
||||
$string_filter->setValue( $value );
|
||||
|
||||
$filter = new Google_Service_AnalyticsData_Filter();
|
||||
$filter->setFieldName( $dimension_name );
|
||||
$filter->setStringFilter( $string_filter );
|
||||
|
||||
$filter_expression = new Google_Service_AnalyticsData_FilterExpression();
|
||||
$filter_expression->setFilter( $filter );
|
||||
|
||||
return $filter_expression;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Google\Site_Kit\Modules\Analytics_4\Report\Metric_Filter\Between_Filter
|
||||
*
|
||||
* @package Google\Site_Kit\Modules\Analytics_4\Report\Metric_Filter
|
||||
* @copyright 2023 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://sitekit.withgoogle.com
|
||||
*/
|
||||
|
||||
namespace Google\Site_Kit\Modules\Analytics_4\Report\Filters;
|
||||
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\Filter as Google_Service_AnalyticsData_Filter;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\FilterExpression as Google_Service_AnalyticsData_FilterExpression;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\BetweenFilter as Google_Service_AnalyticsData_BetweenFilter;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\NumericValue as NumericValue;
|
||||
|
||||
/**
|
||||
* Class for parsing the metric between filter.
|
||||
*
|
||||
* @since 1.111.0
|
||||
* @access private
|
||||
* @ignore
|
||||
*/
|
||||
class Between_Filter {
|
||||
|
||||
/**
|
||||
* Converts the metric filter into the GA4 compatible metric filter expression.
|
||||
*
|
||||
* @since 1.111.0
|
||||
*
|
||||
* @param string $metric_name The metric name.
|
||||
* @param integer $from_value The filter from value.
|
||||
* @param integer $to_value The filter to value.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression instance.
|
||||
*/
|
||||
public function parse_filter_expression( $metric_name, $from_value, $to_value ) {
|
||||
$numeric_from_value = new NumericValue();
|
||||
$numeric_from_value->setInt64Value( $from_value );
|
||||
|
||||
$numeric_to_value = new NumericValue();
|
||||
$numeric_to_value->setInt64Value( $to_value );
|
||||
|
||||
$between_filter = new Google_Service_AnalyticsData_BetweenFilter();
|
||||
$between_filter->setFromValue( $numeric_from_value );
|
||||
$between_filter->setToValue( $numeric_to_value );
|
||||
|
||||
$filter = new Google_Service_AnalyticsData_Filter();
|
||||
$filter->setFieldName( $metric_name );
|
||||
$filter->setBetweenFilter( $between_filter );
|
||||
|
||||
$expression = new Google_Service_AnalyticsData_FilterExpression();
|
||||
$expression->setFilter( $filter );
|
||||
|
||||
return $expression;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Google\Site_Kit\Modules\Analytics_4\Report\Metric_Filter\Numeric_Filter
|
||||
*
|
||||
* @package Google\Site_Kit\Modules\Analytics_4\Report\Metric_Filter
|
||||
* @copyright 2023 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://sitekit.withgoogle.com
|
||||
*/
|
||||
|
||||
namespace Google\Site_Kit\Modules\Analytics_4\Report\Filters;
|
||||
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\Filter as Google_Service_AnalyticsData_Filter;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\FilterExpression as Google_Service_AnalyticsData_FilterExpression;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\NumericFilter as Google_Service_AnalyticsData_NumericFilter;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\NumericValue as NumericValue;
|
||||
|
||||
/**
|
||||
* Class for parsing the metric numeric filter.
|
||||
*
|
||||
* @since 1.111.0
|
||||
* @access private
|
||||
* @ignore
|
||||
*/
|
||||
class Numeric_Filter {
|
||||
|
||||
/**
|
||||
* Converts the metric filter into the GA4 compatible metric filter expression.
|
||||
*
|
||||
* @since 1.111.0
|
||||
*
|
||||
* @param string $metric_name The metric name.
|
||||
* @param string $operation The filter operation.
|
||||
* @param integer $value The filter value.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression instance.
|
||||
*/
|
||||
public function parse_filter_expression( $metric_name, $operation, $value ) {
|
||||
$numeric_value = new NumericValue();
|
||||
$numeric_value->setInt64Value( $value );
|
||||
|
||||
$numeric_filter = new Google_Service_AnalyticsData_NumericFilter();
|
||||
$numeric_filter->setOperation( $operation );
|
||||
$numeric_filter->setValue( $numeric_value );
|
||||
|
||||
$filter = new Google_Service_AnalyticsData_Filter();
|
||||
$filter->setFieldName( $metric_name );
|
||||
$filter->setNumericFilter( $numeric_filter );
|
||||
|
||||
$expression = new Google_Service_AnalyticsData_FilterExpression();
|
||||
$expression->setFilter( $filter );
|
||||
|
||||
return $expression;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,529 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Google\Site_Kit\Modules\Analytics_4\Report\Request
|
||||
*
|
||||
* @package Google\Site_Kit\Modules\Analytics_4\Report
|
||||
* @copyright 2023 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://sitekit.withgoogle.com
|
||||
*/
|
||||
|
||||
namespace Google\Site_Kit\Modules\Analytics_4\Report;
|
||||
|
||||
use Google\Site_Kit\Core\REST_API\Data_Request;
|
||||
use Google\Site_Kit\Core\Validation\Exception\Invalid_Report_Dimensions_Exception;
|
||||
use Google\Site_Kit\Core\Validation\Exception\Invalid_Report_Metrics_Exception;
|
||||
use Google\Site_Kit\Core\Util\URL;
|
||||
use Google\Site_Kit\Modules\Analytics_4\Report;
|
||||
use Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter\In_List_Filter;
|
||||
use Google\Site_Kit\Modules\Analytics_4\Report\Dimension_Filter\String_Filter;
|
||||
use Google\Site_Kit\Modules\Analytics_4\Report\Filters\Numeric_Filter;
|
||||
use Google\Site_Kit\Modules\Analytics_4\Report\Filters\Between_Filter;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\DateRange as Google_Service_AnalyticsData_DateRange;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\Dimension as Google_Service_AnalyticsData_Dimension;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\FilterExpression as Google_Service_AnalyticsData_FilterExpression;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\FilterExpressionList as Google_Service_AnalyticsData_FilterExpressionList;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\RunReportRequest as Google_Service_AnalyticsData_RunReportRequest;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\Metric as Google_Service_AnalyticsData_Metric;
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Class for Analytics 4 report requests.
|
||||
*
|
||||
* @since 1.99.0
|
||||
* @access private
|
||||
* @ignore
|
||||
*/
|
||||
class Request extends Report {
|
||||
|
||||
/**
|
||||
* Creates and executes a new Analytics 4 report request.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param Data_Request $data Data request object.
|
||||
* @param bool $is_shared_request Determines whether the current request is shared or not.
|
||||
* @return RequestInterface|WP_Error Request object on success, or WP_Error on failure.
|
||||
*/
|
||||
public function create_request( Data_Request $data, $is_shared_request ) {
|
||||
$request = new Google_Service_AnalyticsData_RunReportRequest();
|
||||
$request->setKeepEmptyRows( true );
|
||||
$request->setMetricAggregations( array( 'TOTAL', 'MINIMUM', 'MAXIMUM' ) );
|
||||
|
||||
if ( ! empty( $data['limit'] ) ) {
|
||||
$request->setLimit( $data['limit'] );
|
||||
}
|
||||
|
||||
$dimensions = $this->parse_dimensions( $data );
|
||||
if ( ! empty( $dimensions ) ) {
|
||||
if ( $is_shared_request ) {
|
||||
try {
|
||||
$this->validate_shared_dimensions( $dimensions );
|
||||
} catch ( Invalid_Report_Dimensions_Exception $exception ) {
|
||||
return new WP_Error(
|
||||
'invalid_analytics_4_report_dimensions',
|
||||
$exception->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$request->setDimensions( (array) $dimensions );
|
||||
}
|
||||
|
||||
$dimension_filters = $this->parse_dimension_filters( $data );
|
||||
$request->setDimensionFilter( $dimension_filters );
|
||||
|
||||
$metric_filters = $this->parse_metric_filters( $data );
|
||||
if ( ! empty( $metric_filters ) ) {
|
||||
$request->setMetricFilter( $metric_filters );
|
||||
}
|
||||
|
||||
$date_ranges = $this->parse_dateranges( $data );
|
||||
$request->setDateRanges( $date_ranges );
|
||||
|
||||
$metrics = $data['metrics'];
|
||||
if ( is_string( $metrics ) || is_array( $metrics ) ) {
|
||||
if ( is_string( $metrics ) ) {
|
||||
$metrics = explode( ',', $data['metrics'] );
|
||||
} elseif ( is_array( $metrics ) && ! wp_is_numeric_array( $metrics ) ) { // If single object is passed.
|
||||
$metrics = array( $metrics );
|
||||
}
|
||||
|
||||
$metrics = array_filter(
|
||||
array_map(
|
||||
function ( $metric_def ) {
|
||||
$metric = new Google_Service_AnalyticsData_Metric();
|
||||
|
||||
if ( is_string( $metric_def ) ) {
|
||||
$metric->setName( $metric_def );
|
||||
} elseif ( is_array( $metric_def ) ) {
|
||||
$metric->setName( $metric_def['name'] );
|
||||
if ( ! empty( $metric_def['expression'] ) ) {
|
||||
$metric->setExpression( $metric_def['expression'] );
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $metric;
|
||||
},
|
||||
$metrics
|
||||
)
|
||||
);
|
||||
|
||||
if ( ! empty( $metrics ) ) {
|
||||
try {
|
||||
$this->validate_metrics( $metrics );
|
||||
} catch ( Invalid_Report_Metrics_Exception $exception ) {
|
||||
return new WP_Error(
|
||||
'invalid_analytics_4_report_metrics',
|
||||
$exception->getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
if ( $is_shared_request ) {
|
||||
try {
|
||||
$this->validate_shared_metrics( $metrics );
|
||||
} catch ( Invalid_Report_Metrics_Exception $exception ) {
|
||||
return new WP_Error(
|
||||
'invalid_analytics_4_report_metrics',
|
||||
$exception->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$request->setMetrics( $metrics );
|
||||
}
|
||||
}
|
||||
|
||||
// Order by.
|
||||
$orderby = $this->parse_orderby( $data );
|
||||
if ( ! empty( $orderby ) ) {
|
||||
$request->setOrderBys( $orderby );
|
||||
}
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given metrics for a report.
|
||||
*
|
||||
* Metrics must have valid names, matching the regular expression ^[a-zA-Z0-9_]+$ in keeping with the GA4 API.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param Google_Service_AnalyticsData_Metric[] $metrics The metrics to validate.
|
||||
* @throws Invalid_Report_Metrics_Exception Thrown if the metrics are invalid.
|
||||
*/
|
||||
protected function validate_metrics( $metrics ) {
|
||||
$valid_name_expression = '^[a-zA-Z0-9_]+$';
|
||||
|
||||
$invalid_metrics = array_map(
|
||||
function ( $metric ) {
|
||||
return $metric->getName();
|
||||
},
|
||||
array_filter(
|
||||
$metrics,
|
||||
function ( $metric ) use ( $valid_name_expression ) {
|
||||
return ! preg_match( "#$valid_name_expression#", $metric->getName() );
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
if ( count( $invalid_metrics ) > 0 ) {
|
||||
$message = count( $invalid_metrics ) > 1 ? sprintf(
|
||||
/* translators: 1: the regular expression for a valid name, 2: a comma separated list of the invalid metrics. */
|
||||
__(
|
||||
'Metric names should match the expression %1$s: %2$s',
|
||||
'google-site-kit'
|
||||
),
|
||||
$valid_name_expression,
|
||||
join(
|
||||
/* translators: used between list items, there is a space after the comma. */
|
||||
__( ', ', 'google-site-kit' ),
|
||||
$invalid_metrics
|
||||
)
|
||||
) : sprintf(
|
||||
/* translators: 1: the regular expression for a valid name, 2: the invalid metric. */
|
||||
__(
|
||||
'Metric name should match the expression %1$s: %2$s',
|
||||
'google-site-kit'
|
||||
),
|
||||
$valid_name_expression,
|
||||
$invalid_metrics[0]
|
||||
);
|
||||
|
||||
throw new Invalid_Report_Metrics_Exception( $message );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the report metrics for a shared request.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param Google_Service_AnalyticsData_Metric[] $metrics The metrics to validate.
|
||||
* @throws Invalid_Report_Metrics_Exception Thrown if the metrics are invalid.
|
||||
*/
|
||||
protected function validate_shared_metrics( $metrics ) {
|
||||
$valid_metrics = apply_filters(
|
||||
'googlesitekit_shareable_analytics_4_metrics',
|
||||
array(
|
||||
'activeUsers',
|
||||
'averageSessionDuration',
|
||||
'bounceRate',
|
||||
'conversions',
|
||||
'engagedSessions',
|
||||
'engagementRate',
|
||||
'screenPageViews',
|
||||
'screenPageViewsPerSession',
|
||||
'sessions',
|
||||
'sessionConversionRate',
|
||||
'sessionsPerUser',
|
||||
'totalAdRevenue',
|
||||
'totalUsers',
|
||||
)
|
||||
);
|
||||
|
||||
$invalid_metrics = array_diff(
|
||||
array_map(
|
||||
function ( $metric ) {
|
||||
// If there is an expression, it means the name is there as an alias, otherwise the name should be a valid metric name.
|
||||
// Therefore, the expression takes precedence to the name for the purpose of allow-list validation.
|
||||
return ! empty( $metric->getExpression() ) ? $metric->getExpression() : $metric->getName();
|
||||
},
|
||||
$metrics
|
||||
),
|
||||
$valid_metrics
|
||||
);
|
||||
|
||||
if ( count( $invalid_metrics ) > 0 ) {
|
||||
$message = count( $invalid_metrics ) > 1 ? sprintf(
|
||||
/* translators: %s: is replaced with a comma separated list of the invalid metrics. */
|
||||
__(
|
||||
'Unsupported metrics requested: %s',
|
||||
'google-site-kit'
|
||||
),
|
||||
join(
|
||||
/* translators: used between list items, there is a space after the comma. */
|
||||
__( ', ', 'google-site-kit' ),
|
||||
$invalid_metrics
|
||||
)
|
||||
) : sprintf(
|
||||
/* translators: %s: is replaced with the invalid metric. */
|
||||
__(
|
||||
'Unsupported metric requested: %s',
|
||||
'google-site-kit'
|
||||
),
|
||||
$invalid_metrics[0]
|
||||
);
|
||||
|
||||
throw new Invalid_Report_Metrics_Exception( $message );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the report dimensions for a shared request.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param Google_Service_AnalyticsData_Dimension[] $dimensions The dimensions to validate.
|
||||
* @throws Invalid_Report_Dimensions_Exception Thrown if the dimensions are invalid.
|
||||
*/
|
||||
protected function validate_shared_dimensions( $dimensions ) {
|
||||
$valid_dimensions = apply_filters(
|
||||
'googlesitekit_shareable_analytics_4_dimensions',
|
||||
array(
|
||||
'adSourceName',
|
||||
'city',
|
||||
'country',
|
||||
'date',
|
||||
'deviceCategory',
|
||||
'newVsReturning',
|
||||
'pagePath',
|
||||
'pageTitle',
|
||||
'sessionDefaultChannelGroup',
|
||||
'sessionDefaultChannelGrouping',
|
||||
'customEvent:googlesitekit_post_author',
|
||||
'customEvent:googlesitekit_post_categories',
|
||||
'customEvent:googlesitekit_post_date',
|
||||
'customEvent:googlesitekit_post_type',
|
||||
)
|
||||
);
|
||||
|
||||
$invalid_dimensions = array_diff(
|
||||
array_map(
|
||||
function ( $dimension ) {
|
||||
return $dimension->getName();
|
||||
},
|
||||
$dimensions
|
||||
),
|
||||
$valid_dimensions
|
||||
);
|
||||
|
||||
if ( count( $invalid_dimensions ) > 0 ) {
|
||||
$message = count( $invalid_dimensions ) > 1 ? sprintf(
|
||||
/* translators: %s: is replaced with a comma separated list of the invalid dimensions. */
|
||||
__(
|
||||
'Unsupported dimensions requested: %s',
|
||||
'google-site-kit'
|
||||
),
|
||||
join(
|
||||
/* translators: used between list items, there is a space after the comma. */
|
||||
__( ', ', 'google-site-kit' ),
|
||||
$invalid_dimensions
|
||||
)
|
||||
) : sprintf(
|
||||
/* translators: %s: is replaced with the invalid dimension. */
|
||||
__(
|
||||
'Unsupported dimension requested: %s',
|
||||
'google-site-kit'
|
||||
),
|
||||
$invalid_dimensions[0]
|
||||
);
|
||||
|
||||
throw new Invalid_Report_Dimensions_Exception( $message );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses dimension filters and returns a filter expression that should be added to the report request.
|
||||
*
|
||||
* @since 1.106.0
|
||||
*
|
||||
* @param Data_Request $data Data request object.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression to use with the report request.
|
||||
*/
|
||||
protected function parse_dimension_filters( Data_Request $data ) {
|
||||
$expressions = array();
|
||||
|
||||
$reference_url = trim( $this->context->get_reference_site_url(), '/' );
|
||||
$hostnames = URL::permute_site_hosts( URL::parse( $reference_url, PHP_URL_HOST ) );
|
||||
$expressions[] = $this->parse_dimension_filter( 'hostName', $hostnames );
|
||||
|
||||
if ( ! empty( $data['url'] ) ) {
|
||||
$url = str_replace( $reference_url, '', esc_url_raw( $data['url'] ) );
|
||||
$expressions[] = $this->parse_dimension_filter( 'pagePath', $url );
|
||||
}
|
||||
|
||||
if ( is_array( $data['dimensionFilters'] ) ) {
|
||||
foreach ( $data['dimensionFilters'] as $key => $value ) {
|
||||
$expressions[] = $this->parse_dimension_filter( $key, $value );
|
||||
}
|
||||
}
|
||||
|
||||
$filter_expression_list = new Google_Service_AnalyticsData_FilterExpressionList();
|
||||
$filter_expression_list->setExpressions( array_filter( $expressions ) );
|
||||
|
||||
$dimension_filters = new Google_Service_AnalyticsData_FilterExpression();
|
||||
$dimension_filters->setAndGroup( $filter_expression_list );
|
||||
|
||||
return $dimension_filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and returns a single dimension filter.
|
||||
*
|
||||
* @since 1.106.0
|
||||
*
|
||||
* @param string $dimension_name The dimension name.
|
||||
* @param mixed $dimension_value The dimension fileter settings.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression instance.
|
||||
*/
|
||||
protected function parse_dimension_filter( $dimension_name, $dimension_value ) {
|
||||
// Use the string filter type by default.
|
||||
$filter_type = 'stringFilter';
|
||||
if ( isset( $dimension_value['filterType'] ) ) {
|
||||
// If the filterType property is provided, use the explicit filter type then.
|
||||
$filter_type = $dimension_value['filterType'];
|
||||
} elseif ( wp_is_numeric_array( $dimension_value ) ) {
|
||||
// Otherwise, if the dimension has a numeric array of values, we should fall
|
||||
// back to the "in list" filter type.
|
||||
$filter_type = 'inListFilter';
|
||||
}
|
||||
|
||||
if ( 'stringFilter' === $filter_type ) {
|
||||
$filter_class = String_Filter::class;
|
||||
} elseif ( 'inListFilter' === $filter_type ) {
|
||||
$filter_class = In_List_Filter::class;
|
||||
// Ensure that the 'inListFilter' is provided a flat array of values.
|
||||
// Extract the actual values from the 'value' key if present.
|
||||
if ( isset( $dimension_value['value'] ) ) {
|
||||
$dimension_value = $dimension_value['value'];
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
$filter = new $filter_class();
|
||||
$filter_expression = $filter->parse_filter_expression( $dimension_name, $dimension_value );
|
||||
|
||||
if ( ! empty( $dimension_value['notExpression'] ) ) {
|
||||
$not_filter_expression = new Google_Service_AnalyticsData_FilterExpression();
|
||||
$not_filter_expression->setNotExpression( $filter_expression );
|
||||
return $not_filter_expression;
|
||||
}
|
||||
|
||||
return $filter_expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses metric filters and returns a filter expression that should be added to the report request.
|
||||
*
|
||||
* @since 1.111.0
|
||||
*
|
||||
* @param Data_Request $data Data request object.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression to use with the report request.
|
||||
*/
|
||||
protected function parse_metric_filters( Data_Request $data ) {
|
||||
$expressions = array();
|
||||
|
||||
if ( is_array( $data['metricFilters'] ) ) {
|
||||
foreach ( $data['metricFilters'] as $key => $value ) {
|
||||
$expressions[] = $this->parse_metric_filter( $key, $value );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $expressions ) ) {
|
||||
$filter_expression_list = new Google_Service_AnalyticsData_FilterExpressionList();
|
||||
$filter_expression_list->setExpressions( array_filter( $expressions ) );
|
||||
|
||||
$metric_filters = new Google_Service_AnalyticsData_FilterExpression();
|
||||
$metric_filters->setAndGroup( $filter_expression_list );
|
||||
|
||||
return $metric_filters;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and returns a single metric filter.
|
||||
*
|
||||
* @since 1.111.0
|
||||
*
|
||||
* @param string $metric_name The metric name.
|
||||
* @param mixed $metric_value The metric filter settings.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression instance.
|
||||
*/
|
||||
protected function parse_metric_filter( $metric_name, $metric_value ) {
|
||||
// Use the numeric filter type by default.
|
||||
$filter_type = 'numericFilter';
|
||||
if ( isset( $metric_value['filterType'] ) ) {
|
||||
// If the filterType property is provided, use the explicit filter type then.
|
||||
$filter_type = $metric_value['filterType'];
|
||||
}
|
||||
|
||||
if ( 'numericFilter' === $filter_type ) {
|
||||
if ( ! isset( $metric_value['operation'] ) || ! isset( $metric_value['value'] ) ) {
|
||||
return null;
|
||||
}
|
||||
if ( ! isset( $metric_value['value']['int64Value'] ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$filter = new Numeric_Filter();
|
||||
|
||||
} elseif ( 'betweenFilter' === $filter_type ) {
|
||||
if ( ! isset( $metric_value['from_value'] ) || ! isset( $metric_value['to_value'] ) ) {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
! isset( $metric_value['from_value']['int64Value'] ) ||
|
||||
! isset( $metric_value['to_value']['int64Value'] )
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$filter = new Between_Filter();
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
$filter_expression = $this->get_metric_filter_expression(
|
||||
$filter,
|
||||
$metric_name,
|
||||
$metric_value
|
||||
);
|
||||
|
||||
return $filter_expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns correct filter expression instance based on the metric filter instance.
|
||||
*
|
||||
* @since 1.111.0
|
||||
*
|
||||
* @param Numeric_Filter|Between_Filter $filter The metric filter instance.
|
||||
* @param string $metric_name The metric name.
|
||||
* @param mixed $metric_value The metric filter settings.
|
||||
* @return Google_Service_AnalyticsData_FilterExpression The filter expression instance.
|
||||
*/
|
||||
protected function get_metric_filter_expression( $filter, $metric_name, $metric_value ) {
|
||||
if ( $filter instanceof Numeric_Filter ) {
|
||||
$value = $metric_value['value']['int64Value'];
|
||||
|
||||
$filter_expression = $filter->parse_filter_expression(
|
||||
$metric_name,
|
||||
$metric_value['operation'],
|
||||
$value
|
||||
);
|
||||
|
||||
} elseif ( $filter instanceof Between_Filter ) {
|
||||
$from_value = $metric_value['from_value']['int64Value'];
|
||||
$to_value = $metric_value['to_value']['int64Value'];
|
||||
|
||||
$filter_expression = $filter->parse_filter_expression(
|
||||
$metric_name,
|
||||
$from_value,
|
||||
$to_value
|
||||
);
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $filter_expression;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Google\Site_Kit\Modules\Analytics_4\Report\Response
|
||||
*
|
||||
* @package Google\Site_Kit\Modules\Analytics_4\Report
|
||||
* @copyright 2023 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://sitekit.withgoogle.com
|
||||
*/
|
||||
|
||||
namespace Google\Site_Kit\Modules\Analytics_4\Report;
|
||||
|
||||
use Google\Site_Kit\Core\REST_API\Data_Request;
|
||||
use Google\Site_Kit\Modules\Analytics_4\Report;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\DateRange as Google_Service_AnalyticsData_DateRange;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\Row as Google_Service_AnalyticsData_Row;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\RunReportResponse as Google_Service_AnalyticsData_RunReportResponse;
|
||||
|
||||
/**
|
||||
* Class for Analytics 4 report responses.
|
||||
*
|
||||
* @since 1.99.0
|
||||
* @access private
|
||||
* @ignore
|
||||
*/
|
||||
class Response extends Report {
|
||||
|
||||
use Row_Trait;
|
||||
|
||||
/**
|
||||
* Parses the report response, and pads the report data with zero-data rows where rows are missing. This only applies for reports which request a single `date` dimension.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param Data_Request $data Data request object.
|
||||
* @param Google_Service_AnalyticsData_RunReportResponse $response Request response.
|
||||
* @return mixed Parsed response data on success, or WP_Error on failure.
|
||||
*/
|
||||
public function parse_response( Data_Request $data, $response ) {
|
||||
// Return early if the response is not of the expected type.
|
||||
if ( ! $response instanceof Google_Service_AnalyticsData_RunReportResponse ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Get report dimensions and return early if there is either more than one dimension or
|
||||
// the only dimension is not "date".
|
||||
$dimensions = $this->parse_dimensions( $data );
|
||||
if ( count( $dimensions ) !== 1 || $dimensions[0]->getName() !== 'date' ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Get date ranges and return early if there are no date ranges for this report.
|
||||
$date_ranges = $this->get_sorted_dateranges( $data );
|
||||
if ( empty( $date_ranges ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Get all available dates in the report.
|
||||
$existing_rows = array();
|
||||
foreach ( $response->getRows() as $row ) {
|
||||
$dimension_values = $row->getDimensionValues();
|
||||
|
||||
$range = 'date_range_0';
|
||||
if ( count( $dimension_values ) > 1 ) {
|
||||
// Considering this code will only be run when we are requesting a single dimension, `date`,
|
||||
// the implication is that the row will _only_ have an additional dimension when multiple
|
||||
// date ranges are requested.
|
||||
//
|
||||
// In this scenario, the dimension at index 1 will have a value of `date_range_{i}`, where
|
||||
// `i` is the zero-based index of the date range.
|
||||
$range = $dimension_values[1]->getValue();
|
||||
}
|
||||
|
||||
$range = str_replace( 'date_range_', '', $range );
|
||||
$date = $dimension_values[0]->getValue();
|
||||
$key = self::get_response_row_key( $date, is_numeric( $range ) ? $range : false );
|
||||
|
||||
$existing_rows[ $key ] = $row;
|
||||
}
|
||||
|
||||
$metric_headers = $response->getMetricHeaders();
|
||||
$ranges_count = count( $date_ranges );
|
||||
$multiple_ranges = $ranges_count > 1;
|
||||
$rows = array();
|
||||
|
||||
// Add rows for the current date for each date range.
|
||||
self::iterate_date_ranges(
|
||||
$date_ranges,
|
||||
function( $date ) use ( &$rows, $existing_rows, $ranges_count, $metric_headers, $multiple_ranges ) {
|
||||
for ( $i = 0; $i < $ranges_count; $i++ ) {
|
||||
// Copy the existing row if it is available, otherwise create a new zero-value row.
|
||||
$key = self::get_response_row_key( $date, $i );
|
||||
$rows[ $key ] = isset( $existing_rows[ $key ] )
|
||||
? $existing_rows[ $key ]
|
||||
: $this->create_report_row( $metric_headers, $date, $multiple_ranges ? $i : false );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// If we have the same number of rows as in the response at the moment, then
|
||||
// we can return the response without setting the new rows back into the response.
|
||||
$new_rows_count = count( $rows );
|
||||
if ( $new_rows_count <= $response->getRowCount() ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// If we have multiple date ranges, we need to sort rows to have them in
|
||||
// the correct order.
|
||||
if ( $multiple_ranges ) {
|
||||
$rows = self::sort_response_rows( $rows, $date_ranges );
|
||||
}
|
||||
|
||||
// Set updated rows back to the response object.
|
||||
$response->setRows( array_values( $rows ) );
|
||||
$response->setRowCount( $new_rows_count );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response row key composed from the date and the date range index values.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param string $date The date of the row to return key for.
|
||||
* @param int|bool $date_range_index The date range index, or FALSE if no index is available.
|
||||
* @return string The row key.
|
||||
*/
|
||||
protected static function get_response_row_key( $date, $date_range_index ) {
|
||||
return "{$date}_{$date_range_index}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sorted and filtered date ranges received in the request params. All corrupted date ranges
|
||||
* are ignored and not included in the returning list.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param Data_Request $data Data request object.
|
||||
* @return Google_Service_AnalyticsData_DateRange[] An array of AnalyticsData DateRange objects.
|
||||
*/
|
||||
protected function get_sorted_dateranges( Data_Request $data ) {
|
||||
$date_ranges = $this->parse_dateranges( $data );
|
||||
if ( empty( $date_ranges ) ) {
|
||||
return $date_ranges;
|
||||
}
|
||||
|
||||
// Filter out all corrupted date ranges.
|
||||
$date_ranges = array_filter(
|
||||
$date_ranges,
|
||||
function( $range ) {
|
||||
$start = strtotime( $range->getStartDate() );
|
||||
$end = strtotime( $range->getEndDate() );
|
||||
return ! empty( $start ) && ! empty( $end );
|
||||
}
|
||||
);
|
||||
|
||||
// Sort date ranges preserving keys to have the oldest date range at the beginning and
|
||||
// the latest date range at the end.
|
||||
uasort(
|
||||
$date_ranges,
|
||||
function( $a, $b ) {
|
||||
$a_start = strtotime( $a->getStartDate() );
|
||||
$b_start = strtotime( $b->getStartDate() );
|
||||
return $a_start - $b_start;
|
||||
}
|
||||
);
|
||||
|
||||
return $date_ranges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts response rows using the algorithm similar to the one that Analytics 4 uses internally
|
||||
* and returns sorted rows.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param Google_Service_AnalyticsData_Row[] $rows The current report rows.
|
||||
* @param Google_Service_AnalyticsData_DateRange[] $date_ranges The report date ranges.
|
||||
* @return Google_Service_AnalyticsData_Row[] Sorted rows.
|
||||
*/
|
||||
protected static function sort_response_rows( $rows, $date_ranges ) {
|
||||
$sorted_rows = array();
|
||||
$ranges_count = count( $date_ranges );
|
||||
|
||||
self::iterate_date_ranges(
|
||||
$date_ranges,
|
||||
function( $date, $range_index ) use ( &$sorted_rows, $ranges_count, $rows ) {
|
||||
// First take the main date range row.
|
||||
$key = self::get_response_row_key( $date, $range_index );
|
||||
$sorted_rows[ $key ] = $rows[ $key ];
|
||||
|
||||
// Then take all remaining rows.
|
||||
for ( $i = 0; $i < $ranges_count; $i++ ) {
|
||||
if ( $i !== $range_index ) {
|
||||
$key = self::get_response_row_key( $date, $i );
|
||||
$sorted_rows[ $key ] = $rows[ $key ];
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return $sorted_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the date ranges and calls callback for each date in each range.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param Google_Service_AnalyticsData_DateRange[] $date_ranges The report date ranges.
|
||||
* @param callable $callback The callback to execute for each date.
|
||||
*/
|
||||
protected static function iterate_date_ranges( $date_ranges, $callback ) {
|
||||
foreach ( $date_ranges as $date_range_index => $date_range ) {
|
||||
$now = strtotime( $date_range->getStartDate() );
|
||||
$end = strtotime( $date_range->getEndDate() );
|
||||
|
||||
do {
|
||||
call_user_func(
|
||||
$callback,
|
||||
gmdate( 'Ymd', $now ),
|
||||
$date_range_index
|
||||
);
|
||||
|
||||
$now += DAY_IN_SECONDS;
|
||||
} while ( $now <= $end );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Google\Site_Kit\Modules\Analytics_4\Report\Row_Trait
|
||||
*
|
||||
* @package Google\Site_Kit\Modules\Analytics_4\Report
|
||||
* @copyright 2023 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
* @link https://sitekit.withgoogle.com
|
||||
*/
|
||||
|
||||
namespace Google\Site_Kit\Modules\Analytics_4\Report;
|
||||
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\DimensionValue as Google_Service_AnalyticsData_DimensionValue;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\MetricHeader as Google_Service_AnalyticsData_MetricHeader;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\MetricValue as Google_Service_AnalyticsData_MetricValue;
|
||||
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData\Row as Google_Service_AnalyticsData_Row;
|
||||
|
||||
/**
|
||||
* A trait that adds a helper method to create report rows.
|
||||
*
|
||||
* @since 1.99.0
|
||||
* @access private
|
||||
* @ignore
|
||||
*/
|
||||
trait Row_Trait {
|
||||
|
||||
/**
|
||||
* Creates and returns a new zero-value row for provided date and metrics.
|
||||
*
|
||||
* @since 1.99.0
|
||||
*
|
||||
* @param Google_Service_AnalyticsData_MetricHeader[] $metric_headers Metric headers from the report response.
|
||||
* @param string $current_date The current date to create a zero-value row for.
|
||||
* @param int|bool $date_range_index The date range index for the current date.
|
||||
* @param string $default_value The default value to use for metric values in the row.
|
||||
* @return Google_Service_AnalyticsData_Row A new zero-value row instance.
|
||||
*/
|
||||
protected function create_report_row( $metric_headers, $current_date, $date_range_index, $default_value = '0' ) {
|
||||
$dimension_values = array();
|
||||
|
||||
$current_date_dimension_value = new Google_Service_AnalyticsData_DimensionValue();
|
||||
$current_date_dimension_value->setValue( $current_date );
|
||||
$dimension_values[] = $current_date_dimension_value;
|
||||
|
||||
// If we have multiple date ranges, we need to add "date_range_{i}" index to dimension values.
|
||||
if ( false !== $date_range_index ) {
|
||||
$date_range_dimension_value = new Google_Service_AnalyticsData_DimensionValue();
|
||||
$date_range_dimension_value->setValue( "date_range_{$date_range_index}" );
|
||||
$dimension_values[] = $date_range_dimension_value;
|
||||
}
|
||||
|
||||
$metric_values = array();
|
||||
foreach ( $metric_headers as $metric_header ) {
|
||||
$metric_value = new Google_Service_AnalyticsData_MetricValue();
|
||||
$metric_value->setValue( $default_value );
|
||||
|
||||
$metric_values[] = $metric_value;
|
||||
}
|
||||
|
||||
$row = new Google_Service_AnalyticsData_Row();
|
||||
$row->setDimensionValues( $dimension_values );
|
||||
$row->setMetricValues( $metric_values );
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user