谷歌创意素材2
This commit is contained in:
parent
f145391b52
commit
f385f6f2ef
@ -10,6 +10,7 @@ use app\service\GoogleAdsCampaignService;
|
||||
use app\service\GoogleAdsGroupService;
|
||||
use app\service\GoogleAdsAdService;
|
||||
use app\service\GoogleAdsAssetService;
|
||||
use app\service\GoogleAdsAssetRelationService;
|
||||
use app\service\GoogleAdsAccountService;
|
||||
use support\Response;
|
||||
use DI\Annotation\Inject;
|
||||
@ -42,6 +43,12 @@ class GoogleAdsController
|
||||
*/
|
||||
private $googleAdsAssetService;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
* @var GoogleAdsAssetRelationService
|
||||
*/
|
||||
private $googleAdsAssetRelationService;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
* @var GoogleAdsAccountService
|
||||
@ -93,6 +100,17 @@ class GoogleAdsController
|
||||
// 继续处理 Google Ads API 操作
|
||||
return $this->getAssets($options);
|
||||
}
|
||||
public function listAssetRelations(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 继续处理 Google Ads API 操作
|
||||
if($options['asset_type'] == 2){
|
||||
return $this->getVideoAssetRelations($options);
|
||||
}elseif($options['asset_type'] == 4){
|
||||
$this->getAssetRelations($options);
|
||||
}
|
||||
}
|
||||
|
||||
public function listDateDatas(Request $request)
|
||||
{
|
||||
@ -279,6 +297,27 @@ class GoogleAdsController
|
||||
// return $this->successResponse(['assets_list' => $resourceName]);
|
||||
return $this->successResponse(['assets_list' => 'succeed added']);
|
||||
}
|
||||
/**
|
||||
* get assets
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getAssetRelations($options): Response
|
||||
{
|
||||
$resourceName = $this->googleAdsAssetRelationService->runListAssetRelations($options['customer_id']);
|
||||
return $this->successResponse(['assets_relation_list' => $resourceName]);
|
||||
// return $this->successResponse(['assets_relation_list' => 'succeed added']);
|
||||
}
|
||||
|
||||
/**
|
||||
* get assets
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getVideoAssetRelations($options): Response
|
||||
{
|
||||
$resourceName = $this->googleAdsAssetRelationService->runListVideoAssetRelations($options['customer_id']);
|
||||
return $this->successResponse(['assets_relation_list' => $resourceName]);
|
||||
// return $this->successResponse(['assets_relation_list' => 'succeed added']);
|
||||
}
|
||||
|
||||
/**
|
||||
* get date datas
|
||||
|
297
app/event/GoogleAdsAssetRelations.php
Normal file
297
app/event/GoogleAdsAssetRelations.php
Normal file
@ -0,0 +1,297 @@
|
||||
<?php
|
||||
|
||||
namespace app\event;
|
||||
|
||||
use app\service\GoogleAdsAssetRelationService;
|
||||
use app\service\GoogleOAuthService;
|
||||
use Google\ApiCore\ApiException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use support\Db;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use DI\Annotation\Inject;
|
||||
|
||||
//use QL\QueryList;
|
||||
use support\Redis;
|
||||
|
||||
|
||||
class GoogleAdsAssetRelations
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var GoogleOAuthService
|
||||
*/
|
||||
|
||||
private $googleOAuthService;
|
||||
|
||||
|
||||
//微博热榜地址
|
||||
// const url = 'https://library.tiktok.com/api/v1/search?region=GB&type=1&start_time=1666540800&end_time=1666627200';
|
||||
|
||||
const userAgent = 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
||||
|
||||
const IMAGEASSET = 'googleadsassetrelations_image';
|
||||
const VIDEOASSET = 'googleadsassetrelations_video';
|
||||
const limit = 12;
|
||||
const sort_order = 'impression,desc';
|
||||
|
||||
|
||||
// const countries = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE","IT", "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "CH", "TR", "GB"] ;
|
||||
const countries = ["GB", "BE"];
|
||||
|
||||
|
||||
public function listAssetRelations(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 继续处理 Google Ads API 操作
|
||||
return $this->getAssetRelations($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* get asset relations
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getAssetRelations($options)
|
||||
{
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customerId) {
|
||||
$googleAdsAssetRelationService = new GoogleAdsAssetRelationService($customerId);
|
||||
$resourceName = $googleAdsAssetRelationService->runListAssetRelations($customerId);
|
||||
}
|
||||
|
||||
// return $this->successResponse(['ads_list' => $resourceName]);
|
||||
}
|
||||
/**
|
||||
* get asset relations
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getVideoAssetRelations($options)
|
||||
{
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customerId) {
|
||||
$googleAdsAssetRelationService = new GoogleAdsAssetRelationService($customerId);
|
||||
$resourceName = $googleAdsAssetRelationService->runListVideoAssetRelations($customerId);
|
||||
}
|
||||
|
||||
// return $this->successResponse(['ads_list' => $resourceName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 每天爬取tiktok广告
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
try {
|
||||
|
||||
$client = new Client([
|
||||
//允许重定向
|
||||
// 'allow_redirects' => true,
|
||||
]);
|
||||
|
||||
|
||||
// 获取前两天 0 点的时间戳
|
||||
$dayBeforeYesterdayStart = strtotime('-2 days 00:00:00');
|
||||
|
||||
// 获取前一天 0 点的时间戳
|
||||
$yesterdayStart = strtotime('-1 day 00:00:00');
|
||||
$countryCache = Redis::get(self::type . 'lastCountry');
|
||||
//全部跑完跳出
|
||||
if ($countryCache == 'All') {
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($countryCache)) {
|
||||
$countryCache = 'GB';
|
||||
}
|
||||
|
||||
$searchIdCache = Redis::get(self::type . 'lastSearchId');
|
||||
$offsetCache = Redis::get(self::type . 'nextOffset');
|
||||
$totalCache = Redis::get(self::type . 'totalCache');
|
||||
if (!isset($searchIdCache) || empty($searchIdCache)) {
|
||||
$searchIdCache = '';
|
||||
}
|
||||
if (!isset($offsetCache) || empty($searchIdCache)) {
|
||||
$offsetCache = 0;
|
||||
}
|
||||
if (!isset($totalCache) || empty($searchIdCache)) {
|
||||
$totalCache = 0;
|
||||
}
|
||||
|
||||
//判断国家是否跑完。
|
||||
if ($totalCache > 0 && $offsetCache > ceil($totalCache / self::limit)) {
|
||||
$key = array_search($countryCache, self::countries, true);
|
||||
if (in_array($countryCache, self::countries) && isset(self::countries[$key + 1])) {
|
||||
$countryCache = self::countries[$key + 1];
|
||||
dump('更新' . $countryCache . '国家的tiktok Ads 完成');
|
||||
} else {
|
||||
$countryCache = 'All'; //赋值非正常国家的code中断定时任务
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$start_time = $dayBeforeYesterdayStart;
|
||||
$end_time = $yesterdayStart;
|
||||
//当前国家爬取
|
||||
$currentParams = null;
|
||||
$currentParams = ['country' => $countryCache, 'search_id' => $searchIdCache, 'type' => 1, 'start_time' => $start_time, 'end_time' => $end_time];
|
||||
|
||||
|
||||
$url = 'https://library.tiktok.com/api/v1/search?region=' . $currentParams['country'] . '&type=' . $currentParams['type'] . '&start_time=' . $currentParams['start_time'] . '&end_time=' . $currentParams['end_time'];
|
||||
|
||||
$res = json_decode($client->post($url, [
|
||||
'headers' => [
|
||||
'accept' => 'application/json, text/plain, */*',
|
||||
'accept-language' => 'zh-CN,zh;q=0.9',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'cookie: _ttp=2ov8Fc4C2CaNscHJd90O9fMhlpE; _ga=GA1.1.1025820618.1731926196; FPID=FPID2.2.Bcgkp%2Fk%2Bbn5w5YeSMR9wd9VpNHJwTUpkkaEqSdCEa0w%3D.1731926196; FPAU=1.2.944915349.1731926193; FPLC=mbVyryI5aG6IVpAvhs1JsgWjA7FVA6QsCJ7VbXhM7zWoXNp4rcD0IK7FNTTf%2FuOrqeOgqEhTd4NB3hY7q3aDVTGQa3WGHqxkGte4%2BBZxsrpaHFas9kb7DPRXM12T5Q%3D%3D; _ga_TEQXTT9FE4=GS1.1.1732097542.7.0.1732097542.0.0.857840528',
|
||||
'origin' => 'https://library.tiktok.com',
|
||||
'priority' => 'u=1, i',
|
||||
'referer' => 'https://library.tiktok.com/ads?region=AT&start_time=1731945600000&end_time=1732032000000&adv_name=&adv_biz_ids=&query_type=&sort_type=last_shown_date,desc',
|
||||
'sec-ch-ua' => '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-mobile' => '?0',
|
||||
'sec-ch-ua-platform' => '"Windows"',
|
||||
'sec-fetch-dest' => 'empty',
|
||||
'sec-fetch-mode' => 'cors',
|
||||
'sec-fetch-site' => 'same-origin',
|
||||
'user-agent' => self::userAgent,
|
||||
// 'user-agent' => 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
],
|
||||
'json' => [
|
||||
'query' => '',
|
||||
'query_type' => '',
|
||||
'adv_biz_ids' => '',
|
||||
'order' => self::sort_order,
|
||||
'offset' => (int)$offsetCache,
|
||||
'search_id' => $currentParams['search_id'],
|
||||
'limit' => self::limit,
|
||||
],
|
||||
|
||||
])->getBody()->getContents(), true);
|
||||
// dump($res);return; //调试点
|
||||
|
||||
if ($res['search_id'] != $searchIdCache) {
|
||||
$searchIdCache = $res['search_id'];
|
||||
dump('search_id更新 ' . $searchIdCache . ' 成功');
|
||||
}
|
||||
|
||||
|
||||
if ($res['total'] == 0 || $res['code'] != 0) {
|
||||
dump('更新tiktok Ads接口响应异常:' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
return;
|
||||
}
|
||||
$listAdsIds = [];
|
||||
foreach ($res['data'] as $ad) {
|
||||
if ($ad['audit_status'] == 2 || empty($ad['videos'])) {
|
||||
continue; //审核不过或者没视频不采集
|
||||
}
|
||||
|
||||
$imagesJson = is_array($ad['image_urls']) ? json_encode($ad['image_urls']) : json_encode([]);
|
||||
$rejection_info = is_array($ad['rejection_info']) ? json_encode($ad['rejection_info']) : null;
|
||||
// dump($rejection_info);
|
||||
$insertData[$ad['id']] = [
|
||||
'ad_id' => $ad['id'],
|
||||
'name' => $ad['name'],
|
||||
'audit_status' => $ad['audit_status'],
|
||||
'type' => $ad['type'],
|
||||
'first_shown_date' => $ad['first_shown_date'],
|
||||
'last_shown_date' => $ad['last_shown_date'],
|
||||
'image_urls' => $imagesJson,
|
||||
'estimated_audience' => $ad['estimated_audience'],
|
||||
'spent' => $ad['spent'],
|
||||
'impression' => $ad['impression'],
|
||||
'show_mode' => $ad['show_mode'],
|
||||
'rejection_info' => $rejection_info,
|
||||
'sor_audit_status' => $ad['sor_audit_status'],
|
||||
'country_code' => $countryCache,
|
||||
];
|
||||
if (isset($ad['videos']) && !empty($ad['videos'])) {
|
||||
// 遍历 "videos" 数组
|
||||
foreach ($ad['videos'] as $video) {
|
||||
$insertData[$ad['id']]['video_url'] = $video['video_url'];
|
||||
$insertData[$ad['id']]['cover_img'] = $video['cover_img'];
|
||||
}
|
||||
}
|
||||
$listAdsIds = array_column($insertData, 'ad_id');
|
||||
|
||||
}
|
||||
// dump($insertData);return;
|
||||
|
||||
|
||||
if (empty($insertData)) return;
|
||||
|
||||
//开启事务
|
||||
Db::beginTransaction();
|
||||
|
||||
|
||||
//删除原来的旧数据
|
||||
TiktokAd::query()->whereIn('ad_id', array_keys($insertData))->delete();
|
||||
//添加新的数据
|
||||
TiktokAd::query()->insert($insertData);
|
||||
|
||||
//redis缓存
|
||||
Redis::set(self::type, json_encode($insertData, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
//redis缓存 记录更新时间
|
||||
$time = date('Y-m-d H:i:s');
|
||||
Redis::set(self::type . 'time', $time);
|
||||
Redis::set(self::type . 'lastCountry', $countryCache);
|
||||
Redis::set(self::type . 'nextOffset', ++$offsetCache); //记录下一次的offset
|
||||
Redis::set(self::type . 'totalCache', $res['total']);
|
||||
Redis::set(self::type . 'lastSearchId', $searchIdCache);
|
||||
if (!empty($listAdsIds)) {
|
||||
Redis::rPush(self::type . 'AdsIds', ...$listAdsIds);
|
||||
}
|
||||
|
||||
//提交事务
|
||||
Db::commit();
|
||||
//销毁$res
|
||||
unset($res);
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . self::type . '成功');
|
||||
} catch (GuzzleException|\Exception $exception) {
|
||||
//回滚事务
|
||||
Db::rollBack();
|
||||
dump('更' . self::type . '异常:' . $exception->getMessage());
|
||||
dump($exception);
|
||||
}
|
||||
// } catch (ClientExceptionInterface $e) {
|
||||
// // 捕获 4xx 错误
|
||||
// dump( 'Client error: ' . $e->getMessage() . "\n");
|
||||
// } catch (ServerExceptionInterface $e) {
|
||||
// // 捕获 5xx 错误
|
||||
// dump('Server error: ' . $e->getMessage() . "\n");
|
||||
// } catch (TransportExceptionInterface $e) {
|
||||
// // 捕获网络传输错误
|
||||
// dump('Transport error: ' . $e->getMessage() . "\n") ;
|
||||
// } catch (\Exception $e) {
|
||||
// // 捕获所有其他错误
|
||||
// dump('General error: ' . $e->getMessage() . "\n") ;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// 可以加入一些公共方法
|
||||
protected function successResponse($data): Response
|
||||
{
|
||||
return Json([
|
||||
'code' => 0,
|
||||
'msg' => 'ok',
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function errorResponse($code, $message, $data = []): Response
|
||||
{
|
||||
return Json([
|
||||
'code' => $code,
|
||||
'msg' => $message ?: 'error',
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
}
|
@ -25,6 +25,11 @@ class Ad extends Model
|
||||
'ad_group_id' => 'int',
|
||||
'customer_id' => 'int',
|
||||
];
|
||||
|
||||
// 设置json类型字段
|
||||
protected $json = ['metadata'];
|
||||
|
||||
|
||||
// 默认值设置
|
||||
protected $defaults = [
|
||||
'status' => 1, // 广告状态默认值为 'ENABLED'
|
||||
|
@ -7,6 +7,7 @@ use app\event\GoogleAdsCampaigns;
|
||||
use app\event\GoogleAdsGroups;
|
||||
use app\event\GoogleAdsAds;
|
||||
use app\event\GoogleAdsAssets;
|
||||
use app\event\GoogleAdsAssetRelations;
|
||||
use app\event\GoogleAdsDateDatas;
|
||||
use Webman\Event\Event;
|
||||
use Workerman\Crontab\Crontab;
|
||||
@ -24,33 +25,33 @@ class UpdateGoogleAdsTask
|
||||
// 每15分钟执行一次
|
||||
new Crontab('10 */15 * * * *', function () {
|
||||
|
||||
$dayBeforeYesterdayStart = date('Y-m-d', strtotime('-2 day'));
|
||||
dump($dayBeforeYesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始');
|
||||
Event::emit(GoogleAdsDateDatas::type, ['date' => $dayBeforeYesterdayStart]);
|
||||
// $dayBeforeYesterdayStart = date('Y-m-d', strtotime('-2 day'));
|
||||
// dump($dayBeforeYesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始');
|
||||
// Event::emit(GoogleAdsDateDatas::type, ['date' => $dayBeforeYesterdayStart]);
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
// 每15分钟执行一次
|
||||
new Crontab('20 */15 * * * *', function () {
|
||||
$yesterdayStart = date('Y-m-d', strtotime('-1 day'));
|
||||
dump($yesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始');
|
||||
Event::emit(GoogleAdsDateDatas::type, ['date' => $yesterdayStart]);
|
||||
// $yesterdayStart = date('Y-m-d', strtotime('-1 day'));
|
||||
// dump($yesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始');
|
||||
// Event::emit(GoogleAdsDateDatas::type, ['date' => $yesterdayStart]);
|
||||
}
|
||||
);
|
||||
|
||||
// 每15分钟执行一次
|
||||
new Crontab('30 */15 * * * *', function () {
|
||||
//获取今天的 0 点的YYYY-MM-DD格式
|
||||
$todayStart = date('Y-m-d', strtotime('0 day'));
|
||||
dump($todayStart . '更新' . GoogleAdsDateDatas::type . '开始');
|
||||
Event::emit(GoogleAdsDateDatas::type, ['date' => $todayStart]);
|
||||
// $todayStart = date('Y-m-d', strtotime('0 day'));
|
||||
// dump($todayStart . '更新' . GoogleAdsDateDatas::type . '开始');
|
||||
// Event::emit(GoogleAdsDateDatas::type, ['date' => $todayStart]);
|
||||
}
|
||||
);
|
||||
// 每15分钟执行一次
|
||||
new Crontab('40 */15 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsCampaigns::type . '开始');
|
||||
Event::emit(GoogleAdsCampaigns::type, []);
|
||||
// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsCampaigns::type . '开始');
|
||||
// Event::emit(GoogleAdsCampaigns::type, []);
|
||||
}
|
||||
);
|
||||
|
||||
@ -63,15 +64,26 @@ class UpdateGoogleAdsTask
|
||||
|
||||
// 每15分钟执行一次
|
||||
new Crontab('55 */15 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAds::type . '开始');
|
||||
Event::emit(GoogleAdsAds::type, []);
|
||||
// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAds::type . '开始');
|
||||
// Event::emit(GoogleAdsAds::type, []);
|
||||
}
|
||||
|
||||
);
|
||||
// 每15分钟执行一次
|
||||
new Crontab('58 */15 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssets::type . '开始');
|
||||
Event::emit(GoogleAdsAssets::type, []);
|
||||
new Crontab('25 */15 * * * *', function () {
|
||||
// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssets::type . '开始');
|
||||
// Event::emit(GoogleAdsAssets::type, []);
|
||||
}
|
||||
);
|
||||
|
||||
new Crontab('55 */50 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssetRelations::IMAGEASSET . '开始');
|
||||
Event::emit(GoogleAdsAssetRelations::IMAGEASSET, []);
|
||||
});
|
||||
|
||||
new Crontab('55 */51 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssetRelations::VIDEOASSET . '开始');
|
||||
Event::emit(GoogleAdsAssetRelations::VIDEOASSET, []);
|
||||
}
|
||||
);
|
||||
|
||||
|
679
app/service/GoogleAdsAssetRelationService.php
Normal file
679
app/service/GoogleAdsAssetRelationService.php
Normal file
@ -0,0 +1,679 @@
|
||||
<?php
|
||||
|
||||
namespace app\service;
|
||||
|
||||
use app\service\GoogleAdsClientService;
|
||||
use app\model\ThirdUserAdvertiser;
|
||||
use app\util\Helper;
|
||||
use app\util\ArgumentNames;
|
||||
use app\util\ArgumentParser;
|
||||
|
||||
//use Google\Ads\GoogleAds\Lib\V18\GoogleAdsClient;
|
||||
//use Google\Ads\GoogleAds\Util\FieldMasks;
|
||||
//use Google\Ads\GoogleAds\Util\V18\ResourceNames;
|
||||
//use Google\Ads\GoogleAds\V18\Common\ResponsiveSearchAdInfo;
|
||||
//use Google\Ads\GoogleAds\V18\Enums\AdGroupAdStatusEnum\AdGroupAdStatus;
|
||||
//use Google\Ads\GoogleAds\V18\Enums\GoogleAdsFieldCategoryEnum\GoogleAdsFieldCategory;
|
||||
//use Google\Ads\GoogleAds\V18\Enums\GoogleAdsFieldDataTypeEnum\GoogleAdsFieldDataType;
|
||||
//use Google\Ads\GoogleAds\V18\Errors\GoogleAdsError;
|
||||
//use Google\Ads\GoogleAds\V18\Resources\Ad;
|
||||
//use Google\Ads\GoogleAds\V18\Resources\AdGroupAd;
|
||||
//use Google\Ads\GoogleAds\V18\Resources\GoogleAdsField;
|
||||
//use Google\Ads\GoogleAds\V18\Services\AdGroupAdOperation;
|
||||
//use Google\Ads\GoogleAds\V18\Services\AdOperation;
|
||||
//use Google\Ads\GoogleAds\V18\Services\MutateAdGroupAdsRequest;
|
||||
//
|
||||
//use Google\Ads\GoogleAds\V18\Common\AdTextAsset;
|
||||
//use Google\Ads\GoogleAds\V18\Enums\ServedAssetFieldTypeEnum\ServedAssetFieldType;
|
||||
//use Google\Ads\GoogleAds\V18\Services\GoogleAdsRow;
|
||||
//use Google\Ads\GoogleAds\V18\Services\MutateAdsRequest;
|
||||
//use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsFieldsRequest;
|
||||
//use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsRequest;
|
||||
//use Google\Ads\GoogleAds\V18\Services\SearchGoogleAdsStreamRequest;
|
||||
//use Google\Protobuf\Internal\RepeatedField;
|
||||
|
||||
|
||||
use think\facade\Db as ThinkDb;
|
||||
use app\model\Ad as AdModel;
|
||||
use app\model\Asset as AssetModel;
|
||||
use app\model\AssetRelation as AssetRelationModel;
|
||||
|
||||
|
||||
use Google\ApiCore\ApiException;
|
||||
|
||||
class GoogleAdsAssetRelationService extends BaseService
|
||||
{
|
||||
// private $googleAdsClient;
|
||||
private $customerId;
|
||||
|
||||
public function __construct($customerId = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// 从数据库动态获取 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', '未找到该广告主或关联的用户');
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
/* @param int $customerId the customer ID
|
||||
* @param $options
|
||||
* @return mixed
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function runListAssetRelations(int $customerId): mixed
|
||||
{
|
||||
// Creates a single shared budget to be used by the campaigns added below.
|
||||
$assetsResourceName = self::getAssetRelations($customerId);
|
||||
// dump(json_encode($assetsResourceName));
|
||||
if (is_array($assetsResourceName)) {
|
||||
self::saveAssetRelations($assetsResourceName);
|
||||
}
|
||||
// return $assetsResourceName;
|
||||
return 'insert success';
|
||||
}
|
||||
|
||||
|
||||
/* @param int $customerId the customer ID
|
||||
* @param $options
|
||||
* @return mixed
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function runListVideoAssetRelations(int $customerId): mixed
|
||||
{
|
||||
// Creates a single shared budget to be used by the campaigns added below.
|
||||
$assetsResourceName = self::getVideoAssetRelations($customerId);
|
||||
// dump(json_encode($assetsResourceName));
|
||||
if (is_array($assetsResourceName)) {
|
||||
self::saveAssetRelations($assetsResourceName);
|
||||
}
|
||||
// return $assetsResourceName;
|
||||
return 'insert success';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 在数据库中保存广告素材信息
|
||||
* @param $assetsResourceName
|
||||
* @return void
|
||||
*/
|
||||
public static function saveAssetRelations($assetsResourceName)
|
||||
{
|
||||
$tableName = 'bps_google_ads_asset_relations';
|
||||
$tableName = getenv('DB_PG_SCHEMA') ? getenv('DB_PG_SCHEMA') . '.' . $tableName : 'public' . $tableName;
|
||||
foreach ($assetsResourceName as $data) {
|
||||
// 修改后的插入 SQL 语句
|
||||
$sql = "INSERT INTO {$tableName}
|
||||
(asset_id, ad_id, ad_group_id, campaign_id, date, create_at, update_at)
|
||||
VALUES (:asset_id, :ad_id, :ad_group_id, :campaign_id, :date, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (asset_id, ad_id, date)
|
||||
DO NOTHING"; // 如果 (asset_id, ad_id, date) 存在,忽略插入操作
|
||||
|
||||
ThinkDb::execute($sql, $data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $customerId the customer ID
|
||||
*/
|
||||
|
||||
public static function getAssetRelations(int $customerId)
|
||||
{
|
||||
// 获取所有素材
|
||||
// $assets = AssetModel::where('asset_type', 4)->select(); //图片素材
|
||||
|
||||
$resourceNames = AssetModel::where('asset_type', 4)
|
||||
->column('asset_id, resource_name');
|
||||
|
||||
// dump($resourceNames);return($resourceNames);
|
||||
$result = [];
|
||||
foreach ($resourceNames as $resourceName) {
|
||||
// 获取广告表中的所有广告
|
||||
$ads = ThinkDb::table('bps.bps_google_ads_ad')
|
||||
// ->whereRaw("metadata->'marketing_images' @> ?", ['["customers/4060397299/assets/191677352383"]'])
|
||||
// ->whereOrRaw("metadata->'square_marketing_images' @> ?", ['["customers/4060397299/assets/191677352383"]'])
|
||||
->whereRaw("metadata->'marketing_images' @> ?", ['["' . $resourceName['resource_name'] . '"]'])
|
||||
->whereOrRaw("metadata->'square_marketing_images' @> ?", ['["' . $resourceName['resource_name'] . '"]'])
|
||||
->select();
|
||||
|
||||
// $ads = AdModel::where(function ($query) use ($resourceName) {
|
||||
// $query->whereJsonContains('metadata->marketing_images', $resourceName)
|
||||
// ->WhereOrJsonContains('metadata->square_marketing_images', $resourceName);
|
||||
// })->select();
|
||||
// $result[$resourceName['asset_id']] = $ads;
|
||||
|
||||
foreach ($ads as $ad) {
|
||||
$result[$resourceName['asset_id']]['ad_id'] = $ad['ad_id'];
|
||||
$result[$resourceName['asset_id']]['ad_group_id'] = $ad['ad_group_id'];
|
||||
$result[$resourceName['asset_id']]['campaign_id'] = $ad['campaign_id'];
|
||||
$result[$resourceName['asset_id']]['asset_id'] = $resourceName['asset_id'];
|
||||
$result[$resourceName['asset_id']]['date'] = date('Y-m-d');
|
||||
}
|
||||
|
||||
}
|
||||
return $result;
|
||||
// dump('Google Ads Asset synchronization completed.');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $customerId the customer ID
|
||||
*/
|
||||
|
||||
public static function getVideoAssetRelations(int $customerId)
|
||||
{
|
||||
// 获取所有素材
|
||||
// $assets = AssetModel::where('asset_type', 2)->select(); //视频素材
|
||||
|
||||
$resourceNames = AssetModel::where('asset_type', 2)
|
||||
->column('asset_id, resource_name');
|
||||
|
||||
// dump($resourceNames);return($resourceNames);
|
||||
$result = [];
|
||||
foreach ($resourceNames as $resourceName) {
|
||||
// 获取广告表中的所有匹配的广告
|
||||
$ads = ThinkDb::table('bps.bps_google_ads_ad')
|
||||
->whereRaw("metadata->'youtube_videos' @> ?", ['["' . $resourceName['resource_name'] . '"]'])
|
||||
->select();
|
||||
foreach ($ads as $ad) {
|
||||
$result[$resourceName['asset_id']]['ad_id'] = $ad['ad_id'];
|
||||
$result[$resourceName['asset_id']]['ad_group_id'] = $ad['ad_group_id'];
|
||||
$result[$resourceName['asset_id']]['campaign_id'] = $ad['campaign_id'];
|
||||
$result[$resourceName['asset_id']]['asset_id'] = $resourceName['asset_id'];
|
||||
$result[$resourceName['asset_id']]['date'] = date('Y-m-d');
|
||||
}
|
||||
|
||||
}
|
||||
return $result;
|
||||
// dump('Google Ads Asset synchronization completed.');
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This example updates the CPC bid and status for a given ad group. To get ad groups, run
|
||||
* GetAdAds.php.
|
||||
*/
|
||||
/* @param int $customerId the customer ID
|
||||
* @param $options
|
||||
* @return mixed
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function runUpdateAd($options): mixed
|
||||
{
|
||||
// $googleAdsClient = $this->googleAdsClient;
|
||||
$googleAdsClient = new GoogleAdsClientService($options['customer_id']);
|
||||
// Creates a single shared budget to be used by the campaigns added below.
|
||||
|
||||
$resourceNames = self::updateAd($googleAdsClient->getGoogleAdsClient(), $options['customer_id'], $options['group_id'], $options['ad_id'], $options['status']);
|
||||
|
||||
return $resourceNames;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs the updateAd example.
|
||||
*
|
||||
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
|
||||
* @param int $customerId the customer ID
|
||||
* @param int $adGroupId the ad group ID that the ad group ad belongs to
|
||||
* @param int $adId the ID of the ad to pause
|
||||
*/
|
||||
public static function updateAd(
|
||||
GoogleAdsClient $googleAdsClient,
|
||||
int $customerId,
|
||||
int $adGroupId,
|
||||
int $adId,
|
||||
int $status
|
||||
)
|
||||
{
|
||||
// Creates ad group ad resource name.
|
||||
$adGroupAdResourceName = ResourceNames::forAdGroupAd($customerId, $adGroupId, $adId);
|
||||
|
||||
// Creates an ad and sets its status to PAUSED.
|
||||
$adGroupAd = new AdGroupAd();
|
||||
$adGroupAd->setResourceName($adGroupAdResourceName);
|
||||
// $adGroupAd->setStatus(AdGroupAdStatus::PAUSED);
|
||||
$adGroupAd->setStatus($status);
|
||||
|
||||
// Constructs an operation that will pause the ad 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 ad group you want to change.
|
||||
$adGroupAdOperation = new AdGroupAdOperation();
|
||||
$adGroupAdOperation->setUpdate($adGroupAd);
|
||||
$adGroupAdOperation->setUpdateMask(FieldMasks::allSetFieldsOf($adGroupAd));
|
||||
|
||||
// Issues a mutate request to pause the ad group ad.
|
||||
$adGroupAdServiceClient = $googleAdsClient->getAdGroupAdServiceClient();
|
||||
$response = $adGroupAdServiceClient->mutateAdGroupAds(MutateAdGroupAdsRequest::build(
|
||||
$customerId,
|
||||
[$adGroupAdOperation]
|
||||
));
|
||||
|
||||
// Prints the resource name of the paused ad group ad.
|
||||
/** @var AdGroupAd $pausedAdGroupAd */
|
||||
$pausedAdGroupAd = $response->getResults()[0];
|
||||
// printf(
|
||||
// "Ad group ad with resource name: '%s' is paused.%s",
|
||||
// $pausedAdGroupAd->getResourceName(),
|
||||
// PHP_EOL
|
||||
// );
|
||||
return $pausedAdGroupAd->getResourceName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新广告状态
|
||||
*/
|
||||
public function updateAdStatus(int $customerId, int $adGroupId, int $adId, int $status)
|
||||
{
|
||||
// 从数据库获取 Ad
|
||||
$ad = AdModel::find($adId);
|
||||
if (!$ad) {
|
||||
// throw new ValidateException('Ad not found');
|
||||
return false;
|
||||
}
|
||||
// 更新数据库中的状态
|
||||
// $ad->updateStatus($status);
|
||||
if ($this->modifyDbAdStatus($adId, $status)) {
|
||||
// 更新 Google Ads 上的状态
|
||||
// $googleAdsClient = $this->googleAdsClient;
|
||||
$googleAdsClient = new GoogleAdsClientService($customerId);
|
||||
$resourceName = self::updateAd($googleAdsClient->getGoogleAdsClient(), $customerId, $adGroupId, $adId, $status);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取广告状态
|
||||
*/
|
||||
public function getAdStatus(int $adId)
|
||||
{
|
||||
// 从数据库获取 Ad
|
||||
$ad = AdModel::find($adId);
|
||||
if (!$ad) {
|
||||
// throw new ValidateException('Ad not found');
|
||||
}
|
||||
|
||||
// 返回广告状态
|
||||
return $ad->getStatusTextAttr(null, $ad->toArray());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 判断广告是否启用
|
||||
*/
|
||||
// public function isAdEnabled(int $adId)
|
||||
// {
|
||||
// $ad = Ad::find($adId);
|
||||
// if (!$ad) {
|
||||
// throw new ValidateException('Ad not found');
|
||||
// }
|
||||
//
|
||||
// return $ad->isEnabled();
|
||||
// }
|
||||
|
||||
/**
|
||||
* 判断广告是否暂停
|
||||
*/
|
||||
// public function isAdPaused(int $adId)
|
||||
// {
|
||||
// $ad = Ad::find($adId);
|
||||
// if (!$ad) {
|
||||
// throw new ValidateException('Ad not found');
|
||||
// }
|
||||
//
|
||||
// return $ad->isPaused();
|
||||
// }
|
||||
|
||||
/**
|
||||
* 判断广告是否停止
|
||||
*/
|
||||
// public function isAdStopped(int $adId)
|
||||
// {
|
||||
// $ad = Ad::find($adId);
|
||||
// if (!$ad) {
|
||||
// throw new ValidateException('Ad not found');
|
||||
// }
|
||||
//
|
||||
// return $ad->isStopped();
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* This example updates the CPC bid and status for a given ad group. To get ad groups, run
|
||||
* GetAdAds.php.
|
||||
*/
|
||||
/* @param int $customerId the customer ID
|
||||
* @param $options
|
||||
* @return mixed
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function runGetResponsiveSearchAds($options): mixed
|
||||
{
|
||||
// $googleAdsClient = $this->googleAdsClient;
|
||||
$googleAdsClient = new GoogleAdsClientService($options['customer_id']);
|
||||
// Creates a single shared budget to be used by the campaigns added below.
|
||||
if (!isset($options['group_id'])) {
|
||||
$options['group_id'] = null;
|
||||
}
|
||||
$resourceNames = self::getResponsiveSearchAds($googleAdsClient->getGoogleAdsClient(), $options['customer_id'], $options['group_id']);
|
||||
|
||||
return $resourceNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定广告组中未移除的自适应搜索广告。
|
||||
*
|
||||
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
|
||||
* @param int $customerId the customer ID
|
||||
* @param int|null $adGroupId the ad group ID for which responsive search ads will be retrieved.
|
||||
* If `null`, returns from all ad groups
|
||||
*/
|
||||
public static function getResponsiveSearchAds(
|
||||
GoogleAdsClient $googleAdsClient,
|
||||
int $customerId,
|
||||
?int $adGroupId
|
||||
)
|
||||
{
|
||||
$googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
|
||||
|
||||
// Creates a query that retrieves responsive search ads.
|
||||
$query =
|
||||
'SELECT ad_group.id, '
|
||||
. 'ad_group_ad.ad.id, '
|
||||
. 'ad_group_ad.ad.responsive_search_ad.headlines, '
|
||||
. 'ad_group_ad.ad.responsive_search_ad.descriptions, '
|
||||
. 'ad_group_ad.status '
|
||||
. 'FROM ad_group_ad '
|
||||
. 'WHERE ad_group_ad.ad.type = RESPONSIVE_SEARCH_AD '
|
||||
. 'AND ad_group_ad.status != "REMOVED"';
|
||||
if (!is_null($adGroupId)) {
|
||||
$query .= " AND ad_group.id = $adGroupId";
|
||||
}
|
||||
|
||||
// Issues a search request.
|
||||
$response =
|
||||
$googleAdsServiceClient->search(SearchGoogleAdsRequest::build($customerId, $query));
|
||||
|
||||
// Iterates over all rows in all pages and prints the requested field values for
|
||||
// the responsive search ad in each row.
|
||||
$isEmptyResult = true;
|
||||
$resources = [];
|
||||
foreach ($response->iterateAllElements() as $googleAdsRow) {
|
||||
/** @var GoogleAdsRow $googleAdsRow */
|
||||
$isEmptyResult = false;
|
||||
$ad = $googleAdsRow->getAdGroupAd()->getAd();
|
||||
$resource = [];
|
||||
// printf(
|
||||
// "Responsive search ad with resource name '%s' and status '%s' was found.%s",
|
||||
// $ad->getResourceName(),
|
||||
// AdGroupAdStatus::name($googleAdsRow->getAdGroupAd()->getStatus()),
|
||||
// PHP_EOL
|
||||
// );
|
||||
$resource['resource_name'] = $ad->getResourceName();
|
||||
$resource['status'] = AdGroupAdStatus::name($googleAdsRow->getAdGroupAd()->getStatus());
|
||||
$responsiveSearchAdInfo = $ad->getResponsiveSearchAd();
|
||||
// printf(
|
||||
// 'Headlines:%1$s%2$sDescriptions:%1$s%3$s%1$s',
|
||||
// PHP_EOL,
|
||||
// self::convertAdTextAssetsToString($responsiveSearchAdInfo->getHeadlines()),
|
||||
// self::convertAdTextAssetsToString($responsiveSearchAdInfo->getDescriptions())
|
||||
// )
|
||||
$resource['content'] = sprintf(
|
||||
'Headlines:%1$s%2$sDescriptions:%1$s%3$s%1$s',
|
||||
PHP_EOL,
|
||||
self::convertAdTextAssetsToString($responsiveSearchAdInfo->getHeadlines()),
|
||||
self::convertAdTextAssetsToString($responsiveSearchAdInfo->getDescriptions())
|
||||
);
|
||||
$resources[] = $resource;
|
||||
}
|
||||
return $resources;
|
||||
// if ($isEmptyResult) {
|
||||
// print 'No responsive search ads were found.' . PHP_EOL;
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the list of AdTextAsset objects into a string representation.
|
||||
*
|
||||
* @param RepeatedField $assets the list of AdTextAsset objects
|
||||
* @return string the string representation of the provided list of AdTextAsset objects
|
||||
*/
|
||||
private static function convertAdTextAssetsToString(RepeatedField $assets): string
|
||||
{
|
||||
$result = '';
|
||||
foreach ($assets as $asset) {
|
||||
/** @var AdTextAsset $asset */
|
||||
$result .= sprintf(
|
||||
"\t%s pinned to %s.%s",
|
||||
$asset->getText(),
|
||||
ServedAssetFieldType::name($asset->getPinnedField()),
|
||||
PHP_EOL
|
||||
);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This example updates the CPC bid and status for a given ad group. To get ad groups, run
|
||||
* GetAdAds.php.
|
||||
*/
|
||||
/* @param int $customerId the customer ID
|
||||
* @param $options
|
||||
* @return mixed
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function runUpdateResponsiveSearchAd($options): mixed
|
||||
{
|
||||
// $googleAdsClient = $this->googleAdsClient;
|
||||
$googleAdsClient = new GoogleAdsClientService($options['customer_id']);
|
||||
// Creates a single shared budget to be used by the campaigns added below.
|
||||
$resourceName = self::updateResponsiveSearchAd($googleAdsClient->getGoogleAdsClient(), $options['customer_id'], $options['ad_id']);
|
||||
|
||||
return $resourceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* updateResponsiveSearchAd.
|
||||
*
|
||||
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
|
||||
* @param int $customerId the customer ID
|
||||
* @param int $adId the ad ID to update
|
||||
*/
|
||||
// [START update_responsive_search_ad]
|
||||
public static function updateResponsiveSearchAd(
|
||||
GoogleAdsClient $googleAdsClient,
|
||||
int $customerId,
|
||||
int $adId
|
||||
)
|
||||
{
|
||||
// Creates an ad with the specified resource name and other changes.
|
||||
$ad = new Ad([
|
||||
'resource_name' => ResourceNames::forAd($customerId, $adId),
|
||||
'responsive_search_ad' => new ResponsiveSearchAdInfo([
|
||||
// Update some properties of the responsive search ad.
|
||||
'headlines' => [
|
||||
new AdTextAsset([
|
||||
'text' => 'Cruise to Pluto #' . Helper::getShortPrintableDatetime(),
|
||||
'pinned_field' => ServedAssetFieldType::HEADLINE_1
|
||||
]),
|
||||
new AdTextAsset(['text' => 'Tickets on sale now', 'pinned_field' => ServedAssetFieldType::HEADLINE_2]),
|
||||
new AdTextAsset(['text' => 'Buy your ticket now'])
|
||||
],
|
||||
'descriptions' => [
|
||||
new AdTextAsset(['text' => 'Best space cruise ever.']),
|
||||
new AdTextAsset([
|
||||
'text' => 'The most wonderful space experience you will ever have.'])
|
||||
]
|
||||
]),
|
||||
'final_urls' => ['http://www.baidu.com'],
|
||||
'final_mobile_urls' => ['http://www.baidu.com/mobile']
|
||||
]);
|
||||
|
||||
// Constructs an operation that will update the ad, using the FieldMasks to derive the
|
||||
// update mask. This mask tells the Google Ads API which attributes of the ad you want to
|
||||
// change.
|
||||
$adOperation = new AdOperation();
|
||||
$adOperation->setUpdate($ad);
|
||||
$adOperation->setUpdateMask(FieldMasks::allSetFieldsOf($ad));
|
||||
|
||||
// Issues a mutate request to update the ad.
|
||||
$adServiceClient = $googleAdsClient->getAdServiceClient();
|
||||
$response =
|
||||
$adServiceClient->mutateAds(MutateAdsRequest::build($customerId, [$adOperation]));
|
||||
|
||||
// Prints the resource name of the updated ad.
|
||||
/** @var Ad $updatedAd */
|
||||
$updatedAd = $response->getResults()[0];
|
||||
printf(
|
||||
"Updated ad with resource name: '%s'.%s",
|
||||
$updatedAd->getResourceName(),
|
||||
PHP_EOL
|
||||
);
|
||||
return $updatedAd->getResourceName();
|
||||
}
|
||||
// [END update_responsive_search_ad]
|
||||
|
||||
|
||||
/**
|
||||
* 根据给定的前缀搜索 Google Ads 字段,检索到关于这些字段的元数据(metadata)
|
||||
*/
|
||||
/* @param int $customerId the customer ID
|
||||
* @param $options
|
||||
* @return mixed
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function runSearchForGoogleAdsFields($options): mixed
|
||||
{
|
||||
// $googleAdsClient = $this->googleAdsClient;
|
||||
$googleAdsClient = new GoogleAdsClientService($options['customer_id']);
|
||||
// Creates a single shared budget to be used by the campaigns added below.
|
||||
$googleAdsFieldData = self::searchForGoogleAdsFields($googleAdsClient->getGoogleAdsClient(), $options['name_prefix']);
|
||||
|
||||
return $googleAdsFieldData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the example SearchForGoogleAdsFields.
|
||||
*
|
||||
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
|
||||
* @param string $namePrefix the name prefix to use in the query
|
||||
*/
|
||||
public static function searchForGoogleAdsFields(GoogleAdsClient $googleAdsClient, string $namePrefix)
|
||||
{
|
||||
$googleAdsFieldServiceClient = $googleAdsClient->getGoogleAdsFieldServiceClient();
|
||||
// Searches for all fields whose name begins with the specified namePrefix.
|
||||
// A single "%" is the wildcard token in the Google Ads Query language.
|
||||
$query = "SELECT name, category, selectable, filterable, sortable, selectable_with, "
|
||||
. "data_type, is_repeated WHERE name LIKE '$namePrefix%'";
|
||||
$response = $googleAdsFieldServiceClient->searchGoogleAdsFields(
|
||||
SearchGoogleAdsFieldsRequest::build($query)
|
||||
);
|
||||
|
||||
if (iterator_count($response->getIterator()) === 0) {
|
||||
printf(
|
||||
"No GoogleAdsFields found with a name that begins with %s.%s",
|
||||
$namePrefix,
|
||||
PHP_EOL
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Iterates over all rows and prints our the metadata of each matching GoogleAdsField.
|
||||
foreach ($response->iterateAllElements() as $googleAdsField) {
|
||||
/** @var GoogleAdsField $googleAdsField */
|
||||
$fieldInfo = [
|
||||
'name' => $googleAdsField->getName(),
|
||||
'category' => GoogleAdsFieldCategory::name($googleAdsField->getCategory()),
|
||||
'data_type' => GoogleAdsFieldDataType::name($googleAdsField->getDataType()),
|
||||
'selectable' => $googleAdsField->getSelectable() ? 'true' : 'false',
|
||||
'filterable' => $googleAdsField->getFilterable() ? 'true' : 'false',
|
||||
'sortable' => $googleAdsField->getSortable() ? 'true' : 'false',
|
||||
'repeated' => $googleAdsField->getIsRepeated() ? 'true' : 'false',
|
||||
'selectable_with' => []
|
||||
];
|
||||
// Check if there are fields that are selectable with the current field
|
||||
if ($googleAdsField->getSelectableWith()->count() > 0) {
|
||||
$selectableWithFields = iterator_to_array($googleAdsField->getSelectableWith()->getIterator());
|
||||
sort($selectableWithFields); // Sort the fields alphabetically
|
||||
$fieldInfo['selectable_with'] = $selectableWithFields;
|
||||
}
|
||||
|
||||
// Add the field info to the result array
|
||||
$googleAdsFieldData[] = $fieldInfo;
|
||||
//
|
||||
// printf("%s:%s", $googleAdsField->getName(), PHP_EOL);
|
||||
// printf(
|
||||
// " %-16s: %s%s",
|
||||
// "category:",
|
||||
// GoogleAdsFieldCategory::name($googleAdsField->getCategory()),
|
||||
// PHP_EOL
|
||||
// );
|
||||
// printf(
|
||||
// " %-16s: %s%s",
|
||||
// "data type:",
|
||||
// GoogleAdsFieldDataType::name($googleAdsField->getDataType()),
|
||||
// PHP_EOL
|
||||
// );
|
||||
// printf(
|
||||
// " %-16s: %s%s",
|
||||
// "selectable:",
|
||||
// $googleAdsField->getSelectable() ? 'true' : 'false',
|
||||
// PHP_EOL
|
||||
// );
|
||||
// printf(
|
||||
// " %-16s: %s%s",
|
||||
// "filterable:",
|
||||
// $googleAdsField->getFilterable() ? 'true' : 'false',
|
||||
// PHP_EOL
|
||||
// );
|
||||
// printf(
|
||||
// " %-16s: %s%s",
|
||||
// "sortable:",
|
||||
// $googleAdsField->getSortable() ? 'true' : 'false',
|
||||
// PHP_EOL
|
||||
// );
|
||||
// printf(
|
||||
// " %-16s: %s%s",
|
||||
// "repeated:",
|
||||
// $googleAdsField->getIsRepeated() ? 'true' : 'false',
|
||||
// PHP_EOL
|
||||
// );
|
||||
//
|
||||
// if ($googleAdsField->getSelectableWith()->count() > 0) {
|
||||
// // Prints the list of fields that are selectable with the field.
|
||||
// $selectableWithFields =
|
||||
// iterator_to_array($googleAdsField->getSelectableWith()->getIterator());
|
||||
// // Sorts and then prints the list.
|
||||
// sort($selectableWithFields);
|
||||
// print ' selectable with:' . PHP_EOL;
|
||||
// foreach ($selectableWithFields as $selectableWithField) {
|
||||
// /** @var string $selectableWithField */
|
||||
// printf(" $selectableWithField%s", PHP_EOL);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
return $googleAdsFieldData; // Return the result array
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -119,8 +119,8 @@ class GoogleAdsAssetService extends BaseService
|
||||
foreach ($assetsResourceName as $data) {
|
||||
// 修改后的插入 SQL 语句
|
||||
$sql = "INSERT INTO {$tableName}
|
||||
(asset_id, customer_id, asset_type, asset_name, resource_name, asset_url, status, metadata, create_at, update_at)
|
||||
VALUES (:asset_id, :customer_id, :asset_type, :asset_name, :resource_name, :asset_url, :status, :metadata, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
(asset_id, customer_id, asset_type, asset_name, resource_name, asset_url, status, asset_source,metadata, create_at, update_at)
|
||||
VALUES (:asset_id, :customer_id, :asset_type, :asset_name, :resource_name, :asset_url, :status,:source, :metadata, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (asset_id)
|
||||
DO UPDATE SET
|
||||
customer_id = EXCLUDED.customer_id,
|
||||
@ -129,6 +129,7 @@ class GoogleAdsAssetService extends BaseService
|
||||
resource_name = EXCLUDED.resource_name,
|
||||
asset_url = EXCLUDED.asset_url,
|
||||
status = EXCLUDED.status,
|
||||
asset_source = EXCLUDED.asset_source,
|
||||
metadata = EXCLUDED.metadata,
|
||||
update_at = CURRENT_TIMESTAMP"; // update_at 使用 CURRENT_TIMESTAMP 自动更新
|
||||
|
||||
@ -204,6 +205,7 @@ class GoogleAdsAssetService extends BaseService
|
||||
|
||||
$resourceName['status'] = 2; //未定义,先占坑
|
||||
$resourceName['resource_name'] = $googleAdsRow->getAsset()->getResourceName();
|
||||
$resourceName['source'] = $googleAdsRow->getAsset()->getSource();
|
||||
$resourceName['customer_id'] = $googleAdsRow->getCustomer()->getId();
|
||||
|
||||
$resourceNames[] = $resourceName;
|
||||
|
@ -7,6 +7,7 @@ use app\event\GoogleAdsCampaigns;
|
||||
use app\event\GoogleAdsGroups;
|
||||
use app\event\GoogleAdsAds;
|
||||
use app\event\GoogleAdsAssets;
|
||||
use app\event\GoogleAdsAssetRelations;
|
||||
use app\event\GoogleAdsDateDatas;
|
||||
|
||||
|
||||
@ -33,6 +34,12 @@ return [
|
||||
GoogleAdsAssets::type => [
|
||||
[GoogleAdsAssets::class, 'getAssets'],
|
||||
],
|
||||
GoogleAdsAssetRelations::IMAGEASSET => [
|
||||
[GoogleAdsAssetRelations::class, 'getAssetRelations'],
|
||||
],
|
||||
GoogleAdsAssetRelations::VIDEOASSET => [
|
||||
[GoogleAdsAssetRelations::class, 'getVideoAssetRelations'],
|
||||
],
|
||||
|
||||
|
||||
];
|
||||
|
@ -103,6 +103,9 @@ Route::group('/googleads', function () {
|
||||
Route::group('/asset', function () {
|
||||
Route::post('/list', [GoogleAdsController::class, 'listAssets']);
|
||||
});
|
||||
Route::group('/asset_relation', function () {
|
||||
Route::post('/list', [GoogleAdsController::class, 'listAssetRelations']);
|
||||
});
|
||||
Route::group('/ad', function () {
|
||||
Route::post('/update', [GoogleAdsController::class, 'updateAd']);
|
||||
Route::post('/list', [GoogleAdsController::class, 'listAds']);
|
||||
|
Loading…
Reference in New Issue
Block a user