client = $client;
}
/**
* Get report data for campaigns.
*
* @param string $type Report type (campaigns or products).
* @param array $args Query arguments.
*
* @return array
* @throws ExceptionWithResponseData If the report data can't be retrieved.
*/
public function get_report_data( string $type, array $args ): array {
try {
$this->has_converted = 'converted' === $this->container->get( AdsCampaign::class )->get_campaign_convert_status();
if ( 'products' === $type ) {
$query = new AdsProductReportQuery( $args );
} else {
$query = new AdsCampaignReportQuery( $args );
}
$results = $query
->set_client( $this->client, $this->options->get_ads_id() )
->get_results();
$page = $results->getPage();
$this->init_report_totals( $args['fields'] ?? [] );
// Iterate only this page (iterateAllElements will iterate all pages).
foreach ( $page->getIterator() as $row ) {
$this->add_report_row( $type, $row, $args );
}
if ( $page->hasNextPage() ) {
$this->report_data['next_page'] = $page->getNextPageToken();
}
// Sort intervals to generate an ordered graph.
if ( isset( $this->report_data['intervals'] ) ) {
ksort( $this->report_data['intervals'] );
}
$this->remove_report_indexes( [ 'products', 'campaigns', 'intervals' ] );
return $this->report_data;
} catch ( ApiException $e ) {
do_action( 'woocommerce_gla_ads_client_exception', $e, __METHOD__ );
$errors = $this->get_exception_errors( $e );
throw new ExceptionWithResponseData(
/* translators: %s Error message */
sprintf( __( 'Unable to retrieve report data: %s', 'google-listings-and-ads' ), reset( $errors ) ),
$this->map_grpc_code_to_http_status_code( $e ),
null,
[
'errors' => $errors,
'report_type' => $type,
'report_query_args' => $args,
]
);
}
}
/**
* Add data for a report row.
*
* @param string $type Report type (campaigns or products).
* @param GoogleAdsRow $row Report row.
* @param array $args Request arguments.
*/
protected function add_report_row( string $type, GoogleAdsRow $row, array $args ) {
$campaign = $row->getCampaign();
$segments = $row->getSegments();
$metrics = $this->get_report_row_metrics( $row, $args );
if ( 'products' === $type && $segments ) {
$product_id = $segments->getProductItemId();
$this->increase_report_data(
'products',
(string) $product_id,
[
'id' => $product_id,
'name' => $segments->getProductTitle(),
'subtotals' => $metrics,
]
);
}
if ( 'campaigns' === $type && $campaign ) {
$campaign_id = $campaign->getId();
$campaign_name = $campaign->getName();
$campaign_type = CampaignType::label( $campaign->getAdvertisingChannelType() );
$is_converted = $this->has_converted && CampaignType::PERFORMANCE_MAX !== $campaign_type;
$this->increase_report_data(
'campaigns',
(string) $campaign_id,
[
'id' => $campaign_id,
'name' => $campaign_name,
'status' => CampaignStatus::label( $campaign->getStatus() ),
'isConverted' => $is_converted,
'subtotals' => $metrics,
]
);
}
if ( $segments && ! empty( $args['interval'] ) ) {
$interval = $this->get_segment_interval( $args['interval'], $segments );
$this->increase_report_data(
'intervals',
$interval,
[
'interval' => $interval,
'subtotals' => $metrics,
]
);
}
$this->increase_report_totals( $metrics );
}
/**
* Get metrics for a report row.
*
* @param GoogleAdsRow $row Report row.
* @param array $args Request arguments.
*
* @return array
*/
protected function get_report_row_metrics( GoogleAdsRow $row, array $args ): array {
$metrics = $row->getMetrics();
if ( ! $metrics || empty( $args['fields'] ) ) {
return [];
}
$data = [];
foreach ( $args['fields'] as $field ) {
switch ( $field ) {
case 'clicks':
$data['clicks'] = $metrics->getClicks();
break;
case 'impressions':
$data['impressions'] = $metrics->getImpressions();
break;
case 'spend':
$data['spend'] = $this->from_micro( $metrics->getCostMicros() );
break;
case 'sales':
$data['sales'] = $metrics->getConversionsValue();
break;
case 'conversions':
$data['conversions'] = $metrics->getConversions();
break;
}
}
return $data;
}
/**
* Get a unique interval index based on the segments data.
*
* Types:
* day =