customerId = $customerId; } else { $this->customerId = getenv('GOOGLE_ADS_CUSTOMER_ID'); } // 从数据库获取 access_token $refreshToken = $this->getRefreshTokenFromDatabase($this->customerId); // // if (!$refreshToken) { // throw new \Exception("Access token not found for advertiserId: " . $advertiserId); // } // OAuth2 Token Authentication $oAuth2Credential = (new OAuth2TokenBuilder()) ->fromFile() // 如果需要从文件获取其他配置,可以继续使用 fromFile() ->withRefreshToken($refreshToken) // 使用动态获取的 access_token ->build(); // Google Ads Client initialization $this->googleAdsClient = (new GoogleAdsClientBuilder()) ->fromFile() ->withOAuth2Credential($oAuth2Credential) ->build(); } // 从数据库动态获取 google RefreshToken // private function getRefreshTokenFromDatabase($advertiserId) // { // // 通过 advertiser_id 查询 ThirdUserAdvertiser,联表查询 ThirdUser 数据 // $userAdvertiser = ThirdUserAdvertiser::with('googleUser') // 联表查询 user 关联 // ->where('advertiser_id', $advertiserId) // 根据 advertiser_id 查询 // ->find(); // 获取第一个结果 // //// 如果找到广告主数据 // if ($userAdvertiser && $userAdvertiser->googleUser) { // // 获取关联用户的 access_token // return $userAdvertiser->googleUser ? $userAdvertiser->googleUser->access_token : null; // } else { //// return $this->errorResponse('101', '未找到该广告主或关联的用户'); // } // } /** * Runs the example. * * @param int $customerId the customer ID * @param $options * @return mixed * @throws ApiException */ public function runAddCampaign(int $customerId, $options): mixed { $googleAdsClient = $this->googleAdsClient; // Creates a single shared budget to be used by the campaigns added below. $budgetResourceName = self::addCampaignBudget($googleAdsClient, $customerId, $options); // Configures the campaign network options. $networkSettings = new NetworkSettings([ 'target_google_search' => true, 'target_search_network' => true, // Enables Display Expansion on Search campaigns. See // https://support.google.com/google-ads/answer/7193800 to learn more. 'target_content_network' => true, 'target_partner_search_network' => false ]); $campaignOperations = []; for ($i = 0; $i < self::NUMBER_OF_CAMPAIGNS_TO_ADD; $i++) { // Creates a campaign. // [START add_campaigns_1] $campaign = new Campaign([ // 'name' => 'Interplanetary Cruise #' . Helper::getPrintableDatetime(), 'name' => $options['campaign_name'] . rand(10, 99) . ' #' . Helper::getPrintableDatetime(), 'advertising_channel_type' => AdvertisingChannelType::SEARCH, // Recommendation: Set the campaign to PAUSED when creating it to prevent // the ads from immediately serving. Set to ENABLED once you've added // targeting and the ads are ready to serve. 'status' => CampaignStatus::PAUSED, // Sets the bidding strategy and budget. 'manual_cpc' => new ManualCpc(), 'campaign_budget' => $budgetResourceName, // Adds the network settings configured above. 'network_settings' => $networkSettings, // Optional: Sets the start and end dates. 'start_date' => date('Ymd', strtotime('+1 day')), 'end_date' => date('Ymd', strtotime('+1 month')) ]); // [END add_campaigns_1] // Creates a campaign operation. $campaignOperation = new CampaignOperation(); $campaignOperation->setCreate($campaign); $campaignOperations[] = $campaignOperation; } // Issues a mutate request to add campaigns. $campaignServiceClient = $googleAdsClient->getCampaignServiceClient(); $response = $campaignServiceClient->mutateCampaigns( MutateCampaignsRequest::build($customerId, $campaignOperations) ); // printf("Added %d campaigns:%s", $response->getResults()->count(), PHP_EOL); // foreach ($response->getResults() as $addedCampaign) { /** @var Campaign $addedCampaign */ // print "{$addedCampaign->getResourceName()}" . PHP_EOL; $resourceNames[] = $addedCampaign->getResourceName(); } return $resourceNames; } /** * Runs the example. * * @param int $customerId the customer ID * @param $options * @return mixed * @throws ApiException */ public function runAddCampaignBudget(int $customerId, $options): mixed { // if(!$customerId){ // $customerId = $this->customerId; // } $googleAdsClient = $this->googleAdsClient; // Creates a single shared budget to be used by the campaigns added below. $budgetResourceName = self::addCampaignBudget($googleAdsClient, $customerId, $options); return $budgetResourceName; } /** * Creates a new campaign budget in the specified client account. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @return string the resource name of the newly created budget * @throws ApiException */ // [START add_campaigns] private static function addCampaignBudget(GoogleAdsClient $googleAdsClient, int $customerId, $options) { // Creates a campaign budget. $budget = new CampaignBudget([ // 'name' => 'Interplanetary Cruise Budget #' . Helper::getPrintableDatetime(), 'name' => $options['name'] . rand(10, 99) . ' #' . Helper::getPrintableDatetime(), // 'delivery_method' => BudgetDeliveryMethod::STANDARD, 'amount_micros' => $options['amount'] * 1000000 ]); // Creates a campaign budget operation. $campaignBudgetOperation = new CampaignBudgetOperation(); $campaignBudgetOperation->setCreate($budget); // Issues a mutate request. $campaignBudgetServiceClient = $googleAdsClient->getCampaignBudgetServiceClient(); $response = $campaignBudgetServiceClient->mutateCampaignBudgets( MutateCampaignBudgetsRequest::build($customerId, [$campaignBudgetOperation]) ); /** @var CampaignBudget $addedBudget */ $addedBudget = $response->getResults()[0]; // printf("Added budget named '%s'%s", $addedBudget->getResourceName(), PHP_EOL); return $addedBudget->getResourceName(); } // [END add_campaigns] /* @param int $customerId the customer ID * @param $options * @return mixed * @throws ApiException */ public function runListCampaigns(int $customerId): mixed { $googleAdsClient = $this->googleAdsClient; // Creates a single shared budget to be used by the campaigns added below. $campaignsResourceName = self::getCampaigns($googleAdsClient, $customerId); // dump(json_encode($campaignsResourceName)); if (is_array($campaignsResourceName)) { self::saveCampaigns($campaignsResourceName); } return $campaignsResourceName; } /* @param int $customerId the customer ID * @param $options * @return mixed * @throws ApiException */ public function runListDateDatas(int $customerId, $date): mixed { $googleAdsClient = $this->googleAdsClient; // Creates a single shared budget to be used by the campaigns added below. $dayResourceName = self::getDateDatas($googleAdsClient, $customerId, $date); // dump(json_encode($dayResourceName)); if (is_array($dayResourceName)) { self::saveDateDatas($dayResourceName); } return $dayResourceName; } /** * Runs the example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID */ // [START get_campaigns] public static function getCampaigns(GoogleAdsClient $googleAdsClient, int $customerId) { $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); // Creates a query that retrieves all campaigns. // $query = 'SELECT campaign.id,campaign.name,campaign.status,campaign.campaign_budget,campaign_budget.id,campaign_budget.name,campaign_budget.amount_micros FROM campaign ORDER BY campaign.id'; $query = "SELECT campaign.id, campaign.name, campaign.status, campaign.advertising_channel_type, campaign.start_date, campaign.end_date, campaign_budget.amount_micros, customer.id FROM campaign WHERE campaign.status != 'REMOVED' "; // Issues a search stream request. /** @var GoogleAdsServerStreamDecorator $stream */ $stream = $googleAdsServiceClient->searchStream( SearchGoogleAdsStreamRequest::build($customerId, $query) ); $resourceNames = []; // Iterates over all rows in all messages and prints the requested field values for // the campaign in each row. foreach ($stream->iterateAllElements() as $googleAdsRow) { /** @var GoogleAdsRow $googleAdsRow */ // printf( // "Campaign with ID %d and name '%s' was found.BudgetID %s: %d %s", // $googleAdsRow->getCampaign()->getId(), // $googleAdsRow->getCampaign()->getName(), // $googleAdsRow->getCampaignBudget()->getName(), // $googleAdsRow->getCampaignBudget()->getAmountMicros(), // // $googleAdsRow->getCampaignBudget()->getName(), // PHP_EOL // ); $resourceName['campaign_id'] = $googleAdsRow->getCampaign()->getId(); $resourceName['campaign_name'] = $googleAdsRow->getCampaign()->getName(); $resourceName['advertising_channel_type'] = $googleAdsRow->getCampaign()->getAdvertisingChannelType(); $resourceName['status'] = $googleAdsRow->getCampaign()->getStatus(); $resourceName['start_date'] = $googleAdsRow->getCampaign()->getStartDate(); $resourceName['end_date'] = $googleAdsRow->getCampaign()->getEndDate(); $resourceName['budget_amount_micros'] = $googleAdsRow->getCampaignBudget()->getAmountMicros(); $resourceName['customer_id'] = $googleAdsRow->getCustomer()->getId(); $resourceNames[] = $resourceName; } return $resourceNames; } /** * Runs the example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID */ // [START get_campaigns] public static function getDateDatas(GoogleAdsClient $googleAdsClient, int $customerId, $date = '2024-12-19') { $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); // Creates a query that retrieves all campaigns. $query = "SELECT ad_group_ad.ad.id, ad_group_ad.ad.name, ad_group_ad.ad.resource_name, ad_group.id, campaign.id, customer.id, metrics.clicks, metrics.cost_micros, metrics.conversions, metrics.conversions_value, metrics.impressions FROM ad_group_ad WHERE segments.date = '{$date}' ORDER BY ad_group.id ASC LIMIT 10000"; // dump($query);return; // Issues a search stream request. /** @var GoogleAdsServerStreamDecorator $stream */ $stream = $googleAdsServiceClient->searchStream( SearchGoogleAdsStreamRequest::build($customerId, $query) ); $resourceNames = []; // Iterates over all rows in all messages and prints the requested field values for // the campaign in each row. foreach ($stream->iterateAllElements() as $googleAdsRow) { /** @var GoogleAdsRow $googleAdsRow */ $resourceName['ad_id'] = $googleAdsRow->getAdGroupAd()->getAd()->getId(); $resourceName['customer_id'] = $googleAdsRow->getCustomer()->getId(); $resourceName['ad_name'] = $googleAdsRow->getAdGroupAd()->getAd()->getName(); $resourceName['ad_resource_name'] = $googleAdsRow->getAdGroupAd()->getAd()->getResourceName(); $resourceName['ad_group_id'] = $googleAdsRow->getAdGroup()->getId(); $resourceName['campaign_id'] = $googleAdsRow->getCampaign()->getId(); $resourceName['clicks'] = $googleAdsRow->getMetrics()->getClicks(); $resourceName['cost_micros'] = $googleAdsRow->getMetrics()->getCostMicros(); $resourceName['conversions'] = $googleAdsRow->getMetrics()->getConversions(); $resourceName['conversions_value'] = $googleAdsRow->getMetrics()->getConversionsValue(); $resourceName['impressions'] = $googleAdsRow->getMetrics()->getImpressions(); $resourceName['date'] = $date; // $resourceName['budget_id'] = $googleAdsRow->getCampaignBudget()->getId(); $resourceNames[] = $resourceName; } return $resourceNames; } /** * Runs the example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID */ // [START get_campaigns] /** * 在数据库中保存广告系列信息 * @param $campaignsResourceName * @return void */ public static function saveCampaigns($campaignsResourceName) { $tableName = 'bps_google_ads_campaign'; $tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'public' . $tableName; // foreach ($campaignsResourceName as $data) { // $sql = "INSERT INTO {$tableName} // (campaign_id, customer_id, campaign_name, status, advertising_channel_type, start_date, end_date, budget_amount_micros) // VALUES (:campaign_id, :customer_id, :campaign_name, :status, :advertising_channel_type, :start_date, :end_date, :budget_amount_micros)"; // ThinkDb::execute($sql, $data); // } foreach ($campaignsResourceName as $data) { $sql = "INSERT INTO {$tableName} (campaign_id, customer_id, campaign_name, status, advertising_channel_type, start_date, end_date, budget_amount_micros) VALUES (:campaign_id, :customer_id, :campaign_name, :status, :advertising_channel_type, :start_date, :end_date, :budget_amount_micros) ON CONFLICT (campaign_id) DO UPDATE SET customer_id = EXCLUDED.customer_id, campaign_name = EXCLUDED.campaign_name, status = EXCLUDED.status, advertising_channel_type = EXCLUDED.advertising_channel_type, start_date = EXCLUDED.start_date, end_date = EXCLUDED.end_date, budget_amount_micros = EXCLUDED.budget_amount_micros, update_at = EXCLUDED.update_at"; // 你可以根据实际情况决定是否需要更新时间戳 ThinkDb::execute($sql, $data); } } /** * 在数据库中保存广告系列信息 * @param $campaignsResourceName * @return void */ public static function saveDateDatas($dayResourceName) { // dump($campaignsResourceName); foreach ($dayResourceName as $data) { // $sql = "INSERT INTO bps.bps_google_ad_day_data (ad_id, customer_id, ad_name, ad_resource_name, ad_group_id, campaign_id, clicks, cost_micros, conversions, conversions_value, impressions, date) // VALUES (:ad_id, :customer_id, :ad_name, :ad_resource_name, :ad_group_id, :campaign_id, :clicks, :cost_micros, :conversions, :conversions_value, :impressions, :date)"; // ThinkDb::execute($sql, $data); $sql = "INSERT INTO bps.bps_google_ad_day_data (ad_id, customer_id, ad_name, ad_resource_name, ad_group_id, campaign_id, clicks, cost_micros, conversions, conversions_value, impressions, date) VALUES (:ad_id, :customer_id, :ad_name, :ad_resource_name, :ad_group_id, :campaign_id, :clicks, :cost_micros, :conversions, :conversions_value, :impressions, :date) ON CONFLICT (ad_id, date) -- 假设 (ad_id, date) 为唯一约束 DO UPDATE SET customer_id = EXCLUDED.customer_id, ad_name = EXCLUDED.ad_name, ad_resource_name = EXCLUDED.ad_resource_name, ad_group_id = EXCLUDED.ad_group_id, campaign_id = EXCLUDED.campaign_id, clicks = EXCLUDED.clicks, cost_micros = EXCLUDED.cost_micros, conversions = EXCLUDED.conversions, conversions_value = EXCLUDED.conversions_value, impressions = EXCLUDED.impressions, update_at = EXCLUDED.update_at"; // 更新其他字段和更新时间戳 ThinkDb::execute($sql, $data); } } /* @param int $customerId the customer ID * @param $options * @return mixed * @throws ApiException */ public function runListCampaignsNext($options): mixed { $googleAdsClient = $this->googleAdsClient; // Creates a single shared budget to be used by the campaigns added below. $campaigns = self::getCampaignsNext($googleAdsClient, $options['customer_id'], $options['page_token']); return $campaigns; } /** * 获取广告系列列表,支持分页 * * @param GoogleAdsClient $googleAdsClient * @param string $customerId 客户 ID * @param null $pageToken 下一页的令牌 * @return array 广告系列列表及下一页令牌 */ public function getCampaignsNext(GoogleAdsClient $googleAdsClient, $customerId, $pageToken = null) { $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); // 创建查询,获取广告系列信息 $query = "SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id"; // 初始化分页参数 $pageToken = null; // $pageSize = 1000; // 每页1000条记录 $allCampaigns = []; $totalResultsCount = 0; $queryResourceConsumption = 0; // 创建请求对象 $request = new SearchGoogleAdsRequest([ 'customer_id' => $customerId, 'query' => $query, 'page_token' => $pageToken, // 分页令牌 // 'page_size' => $pageSize, // 设置每页的大小 ]); // 调用 search 方法进行数据获取 try { // 发起查询请求,返回 PagedListResponse $response = $googleAdsServiceClient->search($request); // 获取总结果数 $totalResultsCount = $response->getTotalResultsCount(); // 获取查询消耗的资源 $queryResourceConsumption = $response->getQueryResourceConsumption(); // 获取返回结果(PagedListResponse 类型) $this->processSearchGoogleAdsResponse($response, $allCampaigns); // 获取下一页的分页令牌 $pageToken = $response->getNextPageToken(); } catch (ApiException $e) { // 处理异常 printf("API request failed with message: %s\n", $e->getMessage()); } return [ 'campaigns' => $allCampaigns, 'totalResultsCount' => $totalResultsCount, 'queryResourceConsumption' => $queryResourceConsumption ]; } /** * 处理 SearchGoogleAdsResponse 数据并提取广告系列信息 * * @param SearchGoogleAdsResponse $response 查询响应 * @param array $allCampaigns 用于存储广告系列的数组 */ private function processSearchGoogleAdsResponse(SearchGoogleAdsResponse $response, array &$allCampaigns) { // 获取查询结果 foreach ($response->getResults() as $googleAdsRow) { /** @var \Google\Ads\GoogleAds\V18\Resources\Campaign $campaign */ $campaign = $googleAdsRow->getCampaign(); $allCampaigns[] = [ 'id' => $campaign->getId(), 'name' => $campaign->getName(), ]; } // 输出分页的总结果数 printf("Total Results Count: %d\n", $response->getTotalResultsCount()); // 输出查询资源消耗 printf("Query Resource Consumption: %d\n", $response->getQueryResourceConsumption()); // 输出汇总数据(如果存在) if ($summaryRow = $response->getSummaryRow()) { // 处理汇总行(根据需要) printf("Summary Row Metrics: %s\n", $summaryRow); } // 获取下一页的分页令牌 $nextPageToken = $response->getNextPageToken(); if ($nextPageToken) { printf("Next Page Token: %s\n", $nextPageToken); } } /* @param int $customerId the customer ID * @param $options * @return mixed * @throws ApiException */ public function runRemoveCampaign($options): mixed { $googleAdsClient = $this->googleAdsClient; // Creates a single shared budget to be used by the campaigns added below. $resourceName = self::removeCampaign($googleAdsClient, $options['customer_id'], $options['campaign_id']); return $resourceName; } /** * Runs the example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param int $campaignId the ID of the campaign to remove */ public static function removeCampaign( GoogleAdsClient $googleAdsClient, int $customerId, int $campaignId ) { // Creates the resource name of a campaign to remove. $campaignResourceName = ResourceNames::forCampaign($customerId, $campaignId); // Creates a campaign operation. $campaignOperation = new CampaignOperation(); $campaignOperation->setRemove($campaignResourceName); // Issues a mutate request to remove the campaign. $campaignServiceClient = $googleAdsClient->getCampaignServiceClient(); $response = $campaignServiceClient->mutateCampaigns( MutateCampaignsRequest::build($customerId, [$campaignOperation]) ); /** @var Campaign $removedCampaign */ $removedCampaign = $response->getResults()[0]; printf( "Removed campaign with resource name '%s'%s", $removedCampaign->getResourceName(), PHP_EOL ); return $removedCampaign->getResourceName(); } /** * This example updates a campaign by setting the status to `PAUSED`. To get campaigns, run * GetCampaigns.php. */ /* @param int $customerId the customer ID * @param $options * @return mixed * @throws ApiException */ public function runUpdateCampaign($options): mixed { $googleAdsClient = $this->googleAdsClient; // Creates a single shared budget to be used by the campaigns added below. $resourceName = self::updateCampaign($googleAdsClient, $options['customer_id'], $options['campaign_id'], $options['status']); return $resourceName; } /** * Runs the updateCampaign example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param int $campaignId the ID of campaign to update */ public static function updateCampaign( GoogleAdsClient $googleAdsClient, int $customerId, int $campaignId, int $status ) { // Creates a campaign object with the specified resource name and other changes. $campaign = new Campaign([ // 'resource_name' => ResourceNames::forCampaign($customerId, $campaignId), // 'status' => CampaignStatus::PAUSED 'resource_name' => ResourceNames::forCampaign($customerId, $campaignId), 'status' => $status, ]); // Constructs an operation that will update the campaign with the specified resource name, // using the FieldMasks utility to derive the update mask. This mask tells the Google Ads // API which attributes of the campaign you want to change. $campaignOperation = new CampaignOperation(); $campaignOperation->setUpdate($campaign); $campaignOperation->setUpdateMask(FieldMasks::allSetFieldsOf($campaign)); // Issues a mutate request to update the campaign. $campaignServiceClient = $googleAdsClient->getCampaignServiceClient(); $response = $campaignServiceClient->mutateCampaigns(MutateCampaignsRequest::build( $customerId, [$campaignOperation] )); // Prints the resource name of the updated campaign. /** @var Campaign $updatedCampaign */ $updatedCampaign = $response->getResults()[0]; printf( "Updated campaign with resource name: '%s'%s", $updatedCampaign->getResourceName(), PHP_EOL ); return $updatedCampaign->getResourceName(); } /** * 更新广告系列状态 */ public function updateCampaignStatus(int $customerId, int $campaignId, int $status) { // 从数据库获取 Campaign 对象 $campaign = CampaignModel::find($campaignId); // dump($campaign);return; if (!$campaign) { // throw new ValidateException('Campaign not found'); return false; } // 更新本地数据库的状态 if ($this->modifyDbCampaignStatus($campaignId, $status)) { // 更新 Google Ads 上的状态 $googleAdsClient = $this->googleAdsClient; $resourceName = self::updateCampaign($googleAdsClient, $customerId, $campaignId, $status); return true; } return false; } /** * 获取广告活动状态 */ // public function getCampaignStatus(int $campaignId) // { // // 从本地数据库获取状态 // $campaign = CampaignModel::find($campaignId); // if (!$campaign) { // throw new ValidateException('Campaign not found'); // } // // // 获取 Google Ads 状态 // $googleAdsStatus = $this->googleAdsClient->getCampaignStatus($campaignId); // // // 返回 Google Ads 的状态 // return $googleAdsStatus; // } /** * 获取 Google Ads Campaign 状态 */ // public function getCampaignStatus(int $campaignId) // { // try { // // 获取 Google Ads 客户端 // $campaignServiceClient = $this->client->getCampaignServiceClient(); // // // 获取 Campaign 资源 // $resourceName = "customers/{customer_id}/campaigns/{$campaignId}"; // $campaign = $campaignServiceClient->getCampaign($resourceName); // // return $campaign->getStatus(); // } catch (ApiException $e) { // throw new \Exception("Google Ads API error: " . $e->getMessage()); // } // } }