oAuth2Credential = (new OAuth2TokenBuilder()) ->withClientId(env('GOOGLE_ADS_CLIENT_ID')) ->withClientSecret(env('GOOGLE_ADS_CLIENT_SECRET')) ->withRefreshToken(env('GOOGLE_ADS_REFRESH_TOKEN')) ->build(); $this->developerToken = env('GOOGLE_ADS_DEVELOPER_TOKEN'); $this->loginCustomerId = env('GOOGLE_ADS_LOGIN_CUSTOMER_ID'); // MCC ID } /** * Build a GoogleAdsClient scoped to a specific customer ID */ protected function buildClient(string $customerId) { return (new GoogleAdsClientBuilder()) ->withDeveloperToken($this->developerToken) ->withOAuth2Credential($this->oAuth2Credential) ->withLoginCustomerId($customerId) ->withTransport('rest') ->build(); } /** * List all accounts under MCC */ public function listAccounts(): array { $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); $query = << $this->loginCustomerId, 'query' => $query, ]); $response = $service->search($request); $accounts = []; foreach ($response->iterateAllElements() as $row) { $clientData = $row->getCustomerClient(); $accounts[] = [ 'customer_id' => (string) $clientData->getId(), 'id' => $clientData->getId(), 'name' => $clientData->getDescriptiveName(), 'level' => $clientData->getLevel(), 'status' => CustomerStatus::name($clientData->getStatus()), 'resource_name' => $clientData->getResourceName(), 'time_zone' => $clientData->getTimeZone(), 'applied_labels' => $clientData->getAppliedLabels(), 'manager' => $clientData->getManager(), ]; } return $accounts; } public function listCampaigns(string $clientCustomerId): array { $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); $customerId = str_replace('-', '', $clientCustomerId); $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $campaigns = []; foreach ($response->iterateAllElements() as $row) { $c = $row->getCampaign(); $campaigns[] = [ 'id' => $c->getId(), 'name' => $c->getName(), 'status' => CampaignStatus::name($c->getStatus()), 'channel' => AdvertisingChannelType::name($c->getAdvertisingChannelType()), 'sub_channel' => AdvertisingChannelSubType::name($c->getAdvertisingChannelSubType()), 'start_date' => $c->getStartDate(), 'end_date' => $c->getEndDate(), 'resource_name' => $c->getResourceName(), ]; } return $campaigns; } public function listCampaignsMetrics(string $clientCustomerId, string $campaignId, string $startDate, string $endDate): array { $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); $customerId = str_replace('-', '', $clientCustomerId); $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); FacadesLog::info('Google Ads Query', [ 'query' => $query, 'customer_id' => $customerId, ]); $metrics = []; foreach ($response->iterateAllElements() as $row) { $c = $row->getCampaign(); $metrics[] = [ 'id' => $c->getId(), 'name' => $c->getName(), 'date' => $row->getSegments()->getDate(), 'impressions' => $row->getMetrics()->getImpressions(), 'clicks' => $row->getMetrics()->getClicks(), // 'ctr' => round($row->getMetrics()->getCtr() * 100, 2), 'daily_budget' => $row->getCampaignBudget()->getAmountMicros() / 1000000, 'actual_spend' => number_format($row->getMetrics()->getCostMicros() / 1000000, 2, '.', ''), // 'average_cpc' => round($row->getMetrics()->getAverageCpc() / 1000000, 2), 'conversions' => $row->getMetrics()->getConversions(), 'conversions_value' => $row->getMetrics()->getConversionsValue(), 'cost_per_conversion' =>number_format(( $row->getMetrics()->getCostPerConversion() / 1000000), 2, '.', ''), // 'conversions_from_interactions_rate' => round($row->getMetrics()->getConversionsFromInteractionsRate() * 100, 2), 'interactions' => $row->getMetrics()->getInteractions(), 'interaction_rate' => number_format($row->getMetrics()->getInteractionRate() * 100, 2, '.', ''), // 'all_conversions' => $row->getMetrics()->getAllConversions(), // 'view_through_conversions' => $row->getMetrics()->getViewThroughConversions() ]; } return $metrics; } public function listCampaignsMetricsById(string $clientCustomerId, string $campaignId, string $startDate = '', string $endDate = ''): array { $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); $customerId = str_replace('-', '', $clientCustomerId); if (empty($startDate)) { $startDate = date('Y-m-d'); } if (empty($endDate)) { $endDate = date('Y-m-d'); } $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $metrics = []; foreach ($response->iterateAllElements() as $row) { $c = $row->getCampaign(); $metrics[] = [ 'id' => $c->getId(), 'name' => $c->getName(), 'start_date' => $c->getStartDate(), // Actual launch date 'date' => $row->getSegments()->getDate(), 'impressions' => $row->getMetrics()->getImpressions(), 'clicks' => $row->getMetrics()->getClicks(), 'daily_budget' => round($row->getCampaignBudget()->getAmountMicros() / 1000000, 2), 'actual_spend' => round($row->getMetrics()->getCostMicros() / 1000000, 2), 'conversions' => $row->getMetrics()->getConversions(), 'conversions_value' => $row->getMetrics()->getConversionsValue(), 'interactions' => $row->getMetrics()->getInteractions(), 'interaction_rate' => round($row->getMetrics()->getInteractionRate() * 100, 2), ]; } return $metrics; } public function listAdGroupsByCampaignId(string $clientCustomerId, string $campaignId): array { $customerId = str_replace('-', '', $clientCustomerId); $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $adGroups = []; foreach ($response->iterateAllElements() as $row) { $ag = $row->getAdGroup(); $campaign = $row->getCampaign(); $adGroups[] = [ 'ad_group_id' => $ag->getId(), 'ad_group_name' => $ag->getName(), 'status' => AdGroupStatus::name($ag->getStatus()), 'type' => AdGroupType::name($ag->getType()), 'cpc_bid_micros' => round($ag->getCpcBidMicros() / 1000000, 2), 'parent_campaign_id' => $campaign->getId(), 'parent_campaign_name' => $campaign->getName(), ]; } return $adGroups; } public function listAdsByAdGroupId(string $clientCustomerId, string $adGroupId): array { $customerId = str_replace('-', '', $clientCustomerId); $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); // Query the ad_group_ad resource $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $ads = []; foreach ($response->iterateAllElements() as $row) { $adGroupAd = $row->getAdGroupAd(); $ad = $adGroupAd->getAd(); $ads[] = [ 'ad_id' => $ad->getId(), 'type' => AdType::name($ad->getType()), 'status' => AdGroupAdStatus::name($adGroupAd->getStatus()), 'approval_status' => PolicyApprovalStatus::name($adGroupAd->getPolicySummary()->getApprovalStatus()), 'final_urls' => iterator_to_array($ad->getFinalUrls()), 'ad_group_id' => $row->getAdGroup()->getId() ]; } return $ads; } public function listAssetsByCampaignId(string $clientCustomerId, string $campaignId): array { $customerId = str_replace('-', '', $clientCustomerId); $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $assets = []; foreach ($response->iterateAllElements() as $row) { $asset = $row->getAsset(); $ca = $row->getCampaignAsset(); $policy = $asset->getPolicySummary(); // 1. Safe access for policy_summary $policy = $asset->getPolicySummary(); // Check if policy exists before calling methods $approvalStatus = 'NOT_APPLICABLE'; $reviewStatus = 'NOT_APPLICABLE'; if (! is_null($policy)) { $approvalStatus = PolicyApprovalStatus::name($policy->getApprovalStatus()); $reviewStatus = PolicyReviewStatus::name($policy->getReviewStatus()); } $assets[] = [ 'id' => $asset->getId(), 'name' => $asset->getName(), 'added_by' => AssetSource::name($asset->getSource()), 'type' => AssetType::name($asset->getType()), 'use_case' => AssetFieldType::name($ca->getFieldType()), 'approval_status' => $approvalStatus, 'review_status' => $reviewStatus, 'status' => AssetLinkStatus::name($ca->getStatus()), ]; } return $assets; } public function listKeywordsByAdGroupId(string $clientCustomerId, string $adGroupId): array { $customerId = str_replace('-', '', $clientCustomerId); $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $keywords = []; foreach ($response->iterateAllElements() as $row) { $criterion = $row->getAdGroupCriterion(); $keywordInfo = $criterion->getKeyword(); $keywords[] = [ 'keyword_id' => $criterion->getCriterionId(), 'text' => $keywordInfo->getText(), 'match_type' => KeywordMatchType::name($keywordInfo->getMatchType()), 'status' => AdGroupCriterionStatus::name($criterion->getStatus()), 'cpc_bid' => round($criterion->getCpcBidMicros() / 1000000, 2), 'ad_group_id' => $row->getAdGroup()->getId() ]; } return $keywords; } public function listAdGroupMetrics(string $dateFrom, string $dateTo): array { $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); $query = << $this->loginCustomerId, 'query' => $query, ]); $response = $service->search($request); $metrics = []; foreach ($response->iterateAllElements() as $row) { $ag = $row->getAdGroup(); $m = $row->getMetrics(); $segments = $row->getSegments(); $metrics[] = [ 'ad_group_resource_name' => $ag->getResourceName(), 'date' => $segments->getDate(), 'impressions' => $m->getImpressions(), 'clicks' => $m->getClicks(), 'cost_micros' => $m->getCostMicros(), 'conversions' => $m->getConversions(), 'ctr' => $m->getCtr(), 'average_cpc' => $m->getAverageCpc(), ]; } return $metrics; } public function getKeywordMetricsById(string $clientCustomerId, string $keywordId, string $startDate = '', string $endDate = ''): array { $customerId = str_replace('-', '', $clientCustomerId); $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); if (empty($startDate)) { $startDate = date('Y-m-d'); } if (empty($endDate)) { $endDate = date('Y-m-d'); } $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $metrics = []; foreach ($response->iterateAllElements() as $row) { $criterion = $row->getAdGroupCriterion(); $m = $row->getMetrics(); $metrics[] = [ 'keyword_id' => $criterion->getCriterionId(), 'text' => $criterion->getKeyword()->getText(), 'match_type' => KeywordMatchType::name($criterion->getKeyword()->getMatchType()), 'date' => $row->getSegments()->getDate(), 'impressions' => $m->getImpressions(), 'clicks' => $m->getClicks(), 'actual_spend' => round($m->getCostMicros() / 1000000, 2), 'conversions' => $m->getConversions(), ]; } return $metrics; } public function getAdGroupMetricsById(string $clientCustomerId, string $adGroupId, string $startDate = '', string $endDate = ''): array { $customerId = str_replace('-', '', $clientCustomerId); $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); if (empty($startDate)) { $startDate = date('Y-m-d'); } if (empty($endDate)) { $endDate = date('Y-m-d'); } $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $results = []; foreach ($response->iterateAllElements() as $row) { $ag = $row->getAdGroup(); $m = $row->getMetrics(); $results[] = [ 'ad_group_id' => $ag->getId(), 'ad_group_name' => $ag->getName(), 'date' => $row->getSegments()->getDate(), 'status' => AdGroupStatus::name($ag->getStatus()), 'impressions' => $m->getImpressions(), 'clicks' => $m->getClicks(), 'actual_spend' => round($m->getCostMicros() / 1000000, 2), 'conversions' => $m->getConversions(), 'conversion_value' => $m->getConversionsValue(), 'ctr' => $m->getImpressions() > 0 ? round(($m->getClicks() / $m->getImpressions()) * 100, 2) : 0 ]; } return $results; } public function getAdMetricsById(string $clientCustomerId, string $adId, string $startDate = '', string $endDate = ''): array { $customerId = str_replace('-', '', $clientCustomerId); $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); if (empty($startDate)) { $startDate = date('Y-m-d'); } if (empty($endDate)) { $endDate = date('Y-m-d'); } $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $results = []; foreach ($response->iterateAllElements() as $row) { $adGroupAd = $row->getAdGroupAd(); $m = $row->getMetrics(); $results[] = [ 'ad_id' => $adGroupAd->getAd()->getId(), 'ad_type' => AdType::name($adGroupAd->getAd()->getType()), 'date' => $row->getSegments()->getDate(), 'status' => AdGroupAdStatus::name($adGroupAd->getStatus()), 'impressions' => $m->getImpressions(), 'clicks' => $m->getClicks(), 'spend' => round($m->getCostMicros() / 1000000, 2), 'conversions' => $m->getConversions(), 'ad_group_id' => $row->getAdGroup()->getId() ]; } return $results; } public function getAssetMetricsById(string $clientCustomerId, string $assetId, string $startDate = '', string $endDate = ''): array { $customerId = str_replace('-', '', $clientCustomerId); $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); if (empty($startDate)) { $startDate = date('Y-m-d'); } if (empty($endDate)) { $endDate = date('Y-m-d'); } $query = << $customerId, 'query' => $query, ]); $response = $service->search($request); $results = []; foreach ($response->iterateAllElements() as $row) { $asset = $row->getAsset(); $ca = $row->getCampaignAsset(); $m = $row->getMetrics(); $results[] = [ 'asset_id' => $asset->getId(), 'asset_name' => $asset->getName(), 'date' => $row->getSegments()->getDate(), 'field_type' => AssetFieldType::name($ca->getFieldType()), // e.g., SITELINK, CALLOUT 'impressions' => $m->getImpressions(), 'clicks' => $m->getClicks(), 'cost' => round($m->getCostMicros() / 1000000, 2), 'conversions' => $m->getConversions(), 'campaign_id' => $row->getCampaign()->getId() ]; } return $results; } public function getAccountDetails(string $customerId): array { $client = $this->buildClient($this->loginCustomerId); $service = $client->getGoogleAdsServiceClient(); // Querying 'customer' gives you specific settings for that ID $query = "SELECT customer.id, customer.descriptive_name, customer.currency_code, customer.time_zone, customer.tracking_url_template, customer.auto_tagging_enabled, customer.manager, customer.test_account, customer.status FROM customer"; // When querying the 'customer' resource, the customer_id in the request // must match the ID you are querying. $request = new SearchGoogleAdsRequest([ 'customer_id' => $customerId, 'query' => $query, ]); $response = $service->search($request); // Since we are querying a specific ID, we only need the first result $row = $response->iterateAllElements()->current(); if (! $row) { return []; } $customer = $row->getCustomer(); return [ 'id' => $customer->getId(), 'name' => $customer->getDescriptiveName(), 'status' => CustomerStatus::name($customer->getStatus()), 'currency' => $customer->getCurrencyCode(), 'time_zone' => $customer->getTimeZone(), 'is_manager' => $customer->getManager(), 'is_test_account' => $customer->getTestAccount(), 'auto_tagging' => $customer->getAutoTaggingEnabled(), 'tracking_template' => $customer->getTrackingUrlTemplate(), ]; } }