|
@@ -0,0 +1,90 @@
|
|
|
+package com.wechi.adweb.bridge.google.ads.service;
|
|
|
+
|
|
|
+import com.google.ads.googleads.lib.GoogleAdsClient;
|
|
|
+import com.google.ads.googleads.v18.services.GoogleAdsRow;
|
|
|
+import com.google.ads.googleads.v18.services.GoogleAdsServiceClient;
|
|
|
+import com.google.ads.googleads.v18.services.GoogleAdsServiceClient.SearchPagedResponse;
|
|
|
+import com.google.ads.googleads.v18.services.SearchGoogleAdsRequest;
|
|
|
+import com.google.api.core.ApiFuture;
|
|
|
+import com.wechi.adweb.bridge.exception.DataException;
|
|
|
+import com.wechi.adweb.bridge.google.ads.dto.CustomerStatsDTO;
|
|
|
+
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.util.concurrent.ExecutionException;
|
|
|
+import java.util.stream.StreamSupport;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author wfansh
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class GoogleAdsService {
|
|
|
+
|
|
|
+ @Autowired private GoogleAdsClient googleAdsClient;
|
|
|
+
|
|
|
+ public CustomerStatsDTO getCustomerStats(String customerId) throws DataException {
|
|
|
+ try (GoogleAdsServiceClient googleAdsServiceClient =
|
|
|
+ googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
|
|
|
+
|
|
|
+ // 1. Queries customer resource fields, yesterday's cost and optimization score.
|
|
|
+ String customerQuery =
|
|
|
+ "SELECT customer.descriptive_name, customer.currency_code, customer.optimization_score, "
|
|
|
+ + "metrics.cost_micros "
|
|
|
+ + "FROM customer WHERE segments.date DURING YESTERDAY";
|
|
|
+ ApiFuture<SearchPagedResponse> customerResponse =
|
|
|
+ googleAdsServiceClient
|
|
|
+ .searchPagedCallable()
|
|
|
+ .futureCall(
|
|
|
+ SearchGoogleAdsRequest.newBuilder()
|
|
|
+ .setCustomerId(customerId)
|
|
|
+ .setQuery(customerQuery)
|
|
|
+ .build());
|
|
|
+
|
|
|
+ // 2. Queries customer balance via account budgets.
|
|
|
+ String balanceQuery =
|
|
|
+ String.format(
|
|
|
+ "SELECT account_budget.adjusted_spending_limit_micros, account_budget.total_adjustments_micros, "
|
|
|
+ + "account_budget.amount_served_micros "
|
|
|
+ + "FROM account_budget "
|
|
|
+ + "WHERE account_budget.status = 'APPROVED' AND account_budget.approved_end_date_time >= '%s'",
|
|
|
+ LocalDate.now());
|
|
|
+ ApiFuture<SearchPagedResponse> balanceResponse =
|
|
|
+ googleAdsServiceClient
|
|
|
+ .searchPagedCallable()
|
|
|
+ .futureCall(
|
|
|
+ SearchGoogleAdsRequest.newBuilder()
|
|
|
+ .setCustomerId(customerId)
|
|
|
+ .setQuery(balanceQuery)
|
|
|
+ .build());
|
|
|
+
|
|
|
+ // Waits for the completion of the above ApiFuture calls, using get() method.
|
|
|
+ GoogleAdsRow customerResult = customerResponse.get().iterateAll().iterator().next();
|
|
|
+ long balanceMicros =
|
|
|
+ StreamSupport.stream(balanceResponse.get().iterateAll().spliterator(), false)
|
|
|
+ .map(GoogleAdsRow::getAccountBudget)
|
|
|
+ .mapToLong(
|
|
|
+ accountBudget ->
|
|
|
+ accountBudget.getAdjustedSpendingLimitMicros()
|
|
|
+ - accountBudget.getAmountServedMicros())
|
|
|
+ .sum();
|
|
|
+
|
|
|
+ return CustomerStatsDTO.builder()
|
|
|
+ .descriptiveName(customerResult.getCustomer().getDescriptiveName())
|
|
|
+ .currencyCode(customerResult.getCustomer().getCurrencyCode())
|
|
|
+ // Balance.
|
|
|
+ .balanceMicros(balanceMicros)
|
|
|
+ .yesterdayCostMicros(customerResult.getMetrics().getCostMicros())
|
|
|
+ // Optimization score.
|
|
|
+ .optimizationScore(customerResult.getCustomer().getOptimizationScore())
|
|
|
+ .build();
|
|
|
+ } catch (InterruptedException | ExecutionException e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ throw new DataException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|