谷歌创意素材3
This commit is contained in:
parent
f385f6f2ef
commit
e29de81700
@ -63,6 +63,33 @@ class AdController
|
||||
return $this->successResponse($result);
|
||||
}
|
||||
|
||||
public function listAssets(Request $request)
|
||||
{
|
||||
// 获取请求参数
|
||||
$page = $request->input('page', 1); // 页码
|
||||
$pageSize = $request->input('page_size', 20); // 每页数量
|
||||
$keyword = $request->input('keyword', ''); // 关键字搜索
|
||||
$dateRange = $request->input('date_range', 'Last Week'); // 日期范围
|
||||
|
||||
// 获取自定义日期范围
|
||||
$startDate = $request->input('start_date', null); // 开始日期,默认为 null
|
||||
$endDate = $request->input('end_date', null); // 结束日期,默认为 null
|
||||
|
||||
$customerId = 4060397299;
|
||||
|
||||
// 你可以进一步验证日期格式(可选)
|
||||
// if ($startDate && !strtotime($startDate)) {
|
||||
// return response()->json(['error' => 'Invalid start date format'], 400);
|
||||
// }
|
||||
// if ($endDate && !strtotime($endDate)) {
|
||||
// return response()->json(['error' => 'Invalid end date format'], 400);
|
||||
// }
|
||||
|
||||
// 调用 Service 层查询
|
||||
$result = $this->googleAdsReportService->getAssetConversionData($customerId,$page, $pageSize, $keyword, $dateRange, $startDate, $endDate);
|
||||
return $this->successResponse($result);
|
||||
}
|
||||
|
||||
public function listCampaigns(Request $request)
|
||||
{
|
||||
// 获取请求参数
|
||||
|
@ -77,16 +77,18 @@ class UpdateGoogleAdsTask
|
||||
);
|
||||
|
||||
new Crontab('55 */50 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssetRelations::IMAGEASSET . '开始');
|
||||
Event::emit(GoogleAdsAssetRelations::IMAGEASSET, []);
|
||||
// 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, []);
|
||||
// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssetRelations::VIDEOASSET . '开始');
|
||||
// Event::emit(GoogleAdsAssetRelations::VIDEOASSET, []);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
// 每15分钟执行一次
|
||||
// new Crontab('58 */15 * * * *', function () {
|
||||
// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsCampaigns::type . '开始');
|
||||
|
@ -116,9 +116,9 @@ class GoogleAdsAssetRelationService extends BaseService
|
||||
$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)
|
||||
$sql = "INSERT INTO {$tableName}
|
||||
(asset_id, ad_id, ad_group_id, campaign_id, date,month,season,year, create_at, update_at)
|
||||
VALUES (:asset_id, :ad_id, :ad_group_id, :campaign_id, :date,:month,:season,:year, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (asset_id, ad_id, date)
|
||||
DO NOTHING"; // 如果 (asset_id, ad_id, date) 存在,忽略插入操作
|
||||
|
||||
@ -134,6 +134,14 @@ class GoogleAdsAssetRelationService extends BaseService
|
||||
|
||||
public static function getAssetRelations(int $customerId)
|
||||
{
|
||||
$date = date('Y-m-d');
|
||||
// 调用私有方法提取 year, month, season
|
||||
$dateDetails = self::extractDateDetails($date);
|
||||
|
||||
$year = $dateDetails['year'];
|
||||
$month = $dateDetails['month'];
|
||||
$season = $dateDetails['season'];
|
||||
|
||||
// 获取所有素材
|
||||
// $assets = AssetModel::where('asset_type', 4)->select(); //图片素材
|
||||
|
||||
@ -162,7 +170,10 @@ class GoogleAdsAssetRelationService extends BaseService
|
||||
$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');
|
||||
$result[$resourceName['asset_id']]['date'] = $date;
|
||||
$result[$resourceName['asset_id']]['month'] = $month;
|
||||
$result[$resourceName['asset_id']]['season'] = $season;
|
||||
$result[$resourceName['asset_id']]['year'] = $year;
|
||||
}
|
||||
|
||||
}
|
||||
@ -178,6 +189,14 @@ class GoogleAdsAssetRelationService extends BaseService
|
||||
|
||||
public static function getVideoAssetRelations(int $customerId)
|
||||
{
|
||||
$date = date('Y-m-d');
|
||||
// 调用私有方法提取 year, month, season
|
||||
$dateDetails = self::extractDateDetails($date);
|
||||
|
||||
$year = $dateDetails['year'];
|
||||
$month = $dateDetails['month'];
|
||||
$season = $dateDetails['season'];
|
||||
|
||||
// 获取所有素材
|
||||
// $assets = AssetModel::where('asset_type', 2)->select(); //视频素材
|
||||
|
||||
@ -196,7 +215,10 @@ class GoogleAdsAssetRelationService extends BaseService
|
||||
$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');
|
||||
$result[$resourceName['asset_id']]['date'] = $date;
|
||||
$result[$resourceName['asset_id']]['month'] = $month;
|
||||
$result[$resourceName['asset_id']]['season'] = $season;
|
||||
$result[$resourceName['asset_id']]['year'] = $year;
|
||||
}
|
||||
|
||||
}
|
||||
@ -206,6 +228,39 @@ class GoogleAdsAssetRelationService extends BaseService
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从日期字符串中提取年、月、季节信息,并返回这些信息
|
||||
*
|
||||
* @param string $date 日期,格式为 'Y-m-d'
|
||||
* @return array 包含 year, month 和 season 的数组
|
||||
*/
|
||||
private static function extractDateDetails($date)
|
||||
{
|
||||
$dateObj = new DateTime($date); // 将日期字符串转换为 DateTime 对象
|
||||
|
||||
// 提取年和月
|
||||
$year = (int)$dateObj->format('Y');
|
||||
$month = (int)$dateObj->format('m');
|
||||
|
||||
// 计算季度
|
||||
if ($month >= 1 && $month <= 3) {
|
||||
$season = (int)$dateObj->format('Ym') . '01'; // Q1
|
||||
} elseif ($month >= 4 && $month <= 6) {
|
||||
$season = (int)$dateObj->format('Ym') . '02'; // Q2
|
||||
} elseif ($month >= 7 && $month <= 9) {
|
||||
$season = (int)$dateObj->format('Ym') . '03'; // Q3
|
||||
} else {
|
||||
$season = (int)$dateObj->format('Ym') . '04'; // Q4
|
||||
}
|
||||
|
||||
return [
|
||||
'year' => $year,
|
||||
'month' => $month,
|
||||
'season' => $season
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This example updates the CPC bid and status for a given ad group. To get ad groups, run
|
||||
* GetAdAds.php.
|
||||
|
@ -304,6 +304,14 @@ class GoogleAdsCampaignService extends BaseService
|
||||
|
||||
public static function getDateDatas(GoogleAdsClient $googleAdsClient, int $customerId, $date = '2024-12-19')
|
||||
{
|
||||
// 调用私有方法提取 year, month, season
|
||||
$dateDetails = self::extractDateDetails($date);
|
||||
|
||||
$year = $dateDetails['year'];
|
||||
$month = $dateDetails['month'];
|
||||
$season = $dateDetails['season'];
|
||||
|
||||
|
||||
$googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
|
||||
|
||||
// Creates a query that retrieves all campaigns.
|
||||
@ -331,12 +339,51 @@ class GoogleAdsCampaignService extends BaseService
|
||||
$resourceName['conversions_value'] = $googleAdsRow->getMetrics()->getConversionsValue();
|
||||
$resourceName['impressions'] = $googleAdsRow->getMetrics()->getImpressions();
|
||||
$resourceName['date'] = $date;
|
||||
$resourceName['month'] = $month;
|
||||
$resourceName['season'] = $season;
|
||||
$resourceName['year'] = $year;
|
||||
|
||||
|
||||
|
||||
// $resourceName['budget_id'] = $googleAdsRow->getCampaignBudget()->getId();
|
||||
$resourceNames[] = $resourceName;
|
||||
}
|
||||
return $resourceNames;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从日期字符串中提取年、月、季节信息,并返回这些信息
|
||||
*
|
||||
* @param string $date 日期,格式为 'Y-m-d'
|
||||
* @return array 包含 year, month 和 season 的数组
|
||||
*/
|
||||
private static function extractDateDetails($date)
|
||||
{
|
||||
$dateObj = new DateTime($date); // 将日期字符串转换为 DateTime 对象
|
||||
|
||||
// 提取年和月
|
||||
$year = (int) $dateObj->format('Y');
|
||||
$month = (int) $dateObj->format('m');
|
||||
|
||||
// 计算季度
|
||||
if ($month >= 1 && $month <= 3) {
|
||||
$season = (int) $dateObj->format('Ym') . '01'; // Q1
|
||||
} elseif ($month >= 4 && $month <= 6) {
|
||||
$season = (int) $dateObj->format('Ym') . '02'; // Q2
|
||||
} elseif ($month >= 7 && $month <= 9) {
|
||||
$season = (int) $dateObj->format('Ym') . '03'; // Q3
|
||||
} else {
|
||||
$season = (int) $dateObj->format('Ym') . '04'; // Q4
|
||||
}
|
||||
|
||||
return [
|
||||
'year' => $year,
|
||||
'month' => $month,
|
||||
'season' => $season
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the example.
|
||||
*
|
||||
@ -395,9 +442,9 @@ class GoogleAdsCampaignService extends BaseService
|
||||
// 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) 为唯一约束
|
||||
(ad_id, customer_id, ad_name, ad_resource_name, ad_group_id, campaign_id, clicks, cost_micros, conversions, conversions_value, impressions, date, month, season, year)
|
||||
VALUES (:ad_id, :customer_id, :ad_name, :ad_resource_name, :ad_group_id, :campaign_id, :clicks, :cost_micros, :conversions, :conversions_value, :impressions, :date, :month, :season, :year)
|
||||
ON CONFLICT (ad_id, date) -- 假设 (ad_id, date) 为唯一约束
|
||||
DO UPDATE SET
|
||||
customer_id = EXCLUDED.customer_id,
|
||||
ad_name = EXCLUDED.ad_name,
|
||||
@ -409,6 +456,9 @@ class GoogleAdsCampaignService extends BaseService
|
||||
conversions = EXCLUDED.conversions,
|
||||
conversions_value = EXCLUDED.conversions_value,
|
||||
impressions = EXCLUDED.impressions,
|
||||
month = EXCLUDED.month,
|
||||
season = EXCLUDED.season,
|
||||
year = EXCLUDED.year,
|
||||
update_at = EXCLUDED.update_at"; // 更新其他字段和更新时间戳
|
||||
|
||||
ThinkDb::execute($sql, $data);
|
||||
|
@ -6,10 +6,12 @@ use app\model\Ad;
|
||||
use app\model\DayData;
|
||||
use app\model\Campaign;
|
||||
use app\model\AdGroup;
|
||||
use app\model\Asset;
|
||||
use app\model\AssetRelation;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
use think\db\exception\DbException;
|
||||
use think\facade\Db;
|
||||
use think\facade\Db as ThinkDb;
|
||||
use think\model\Collection;
|
||||
|
||||
class GoogleAdsReportService
|
||||
@ -603,4 +605,294 @@ class GoogleAdsReportService
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取广告资产报告
|
||||
*
|
||||
* @param string $keyword 关键词(广告素材名称模糊搜索)
|
||||
* @param string $dateRange 日期范围:Today, Yesterday, Last Week, Last Month, Last Year
|
||||
* @param string|null $startDate 起始日期(可选)
|
||||
* @param string|null $endDate 结束日期(可选)
|
||||
* @param int $page 当前页码
|
||||
* @param int $pageSize 每页数量
|
||||
* @return array
|
||||
*/
|
||||
public function getAssetConversionData($customerId, $page, $pageSize, $keyword, $dateRange, $startDate = null, $endDate = null)
|
||||
{
|
||||
|
||||
$isSameMonth = true; // 判断是否跨月
|
||||
$currentMonth = date('Y-m'); //一个月内的统计需要确定是什么月份。
|
||||
if ($startDate && $endDate) {
|
||||
// 比较日期的年月是否相同,若不同则为跨月
|
||||
$isSameMonth = date('Y-m', strtotime($startDate)) === date('Y-m', strtotime($endDate));
|
||||
if ($isSameMonth) {
|
||||
$currentMonth = date('Y-m', strtotime($startDate));
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 获取符合条件的 ad_id 列表,并且筛选 AssetRelation 的 date 字段
|
||||
$adIdsQuery = AssetRelation::alias('r')
|
||||
->leftJoin('bps.bps_google_ads_asset a', 'r.asset_id = a.asset_id') // 关联资产表
|
||||
->where(function ($query) use ($keyword) {
|
||||
if ($keyword) {
|
||||
$query->where('a.asset_name', 'like', '%' . $keyword . '%'); // 关键词模糊匹配
|
||||
}
|
||||
});
|
||||
$adIdsQuery->where('a.customer_id', '=', $customerId);
|
||||
// 日期范围处理,筛选 AssetRelation 的 date 字段
|
||||
if ($startDate && $endDate) {
|
||||
$adIdsQuery->whereBetween('r.date', [$startDate, $endDate]);
|
||||
} else {
|
||||
switch ($dateRange) {
|
||||
case 'Today':
|
||||
$adIdsQuery->where('r.date', '=', date('Y-m-d'));
|
||||
$currentMonth = date('Y-m');
|
||||
$isSameMonth = true;
|
||||
break;
|
||||
case 'Yesterday':
|
||||
$adIdsQuery->where('r.date', '=', date('Y-m-d', strtotime('-1 day')));
|
||||
$currentMonth = date('Y-m', strtotime('-1 day'));
|
||||
$isSameMonth = true;
|
||||
break;
|
||||
case 'Last Week':
|
||||
$adIdsQuery->where('r.date', '>=', date('Y-m-d', strtotime('-1 week')));
|
||||
// 比较日期的年月是否相同,若不同则为跨月
|
||||
$isSameMonth = date('Y-m', strtotime('-1 week')) === date('Y-m');
|
||||
break;
|
||||
case 'Last Month':
|
||||
$adIdsQuery->where('r.date', '>=', date('Y-m-d', strtotime('-1 month')));
|
||||
$isSameMonth = false;
|
||||
break;
|
||||
case 'Last Year':
|
||||
$adIdsQuery->where('r.date', '>=', date('Y-m-d', strtotime('-1 year')));
|
||||
$isSameMonth = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 获取唯一的 ad_id 列表
|
||||
$adIds = $adIdsQuery->distinct(true)->column('r.ad_id');
|
||||
// dump($adIds);return($adIds);
|
||||
|
||||
// 2. 根据 ad_id 和日期范围去查询 DayData 表,按 ad_id 和日期聚合统计
|
||||
$dayDataQuery = DayData::alias('d')
|
||||
// ->leftJoin('bps.bps_google_ads_campaign c', 'd.campaign_id = c.campaign_id') // 关联广告系列表(如果有)
|
||||
// ->leftJoin('bps.bps_google_ads_ad_group ag', 'd.ad_group_id = ag.ad_group_id') // 关联广告组表(如果有)
|
||||
->whereIn('d.ad_id', $adIds) // 使用 ad_id 过滤
|
||||
->where(function ($query) use ($startDate, $endDate, $dateRange) {
|
||||
// 日期范围的筛选
|
||||
if ($startDate && $endDate) {
|
||||
$query->whereBetween('d.date', [$startDate, $endDate]);
|
||||
} else {
|
||||
switch ($dateRange) {
|
||||
case 'Today':
|
||||
$query->where('d.date', '=', date('Y-m-d'));
|
||||
break;
|
||||
case 'Yesterday':
|
||||
$query->where('d.date', '=', date('Y-m-d', strtotime('-1 day')));
|
||||
break;
|
||||
case 'Last Week':
|
||||
$query->where('d.date', '>=', date('Y-m-d', strtotime('-1 week')));
|
||||
break;
|
||||
case 'Last Month':
|
||||
$query->where('d.date', '>=', date('Y-m-d', strtotime('-1 month')));
|
||||
break;
|
||||
case 'Last Year':
|
||||
$query->where('d.date', '>=', date('Y-m-d', strtotime('-1 year')));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 如果跨月,按月聚合;如果不跨月,按 ad_id 聚合
|
||||
if (!$isSameMonth) {
|
||||
$dayDataQuery->group("d.month,d.ad_id,d.ad_name, d.ad_resource_name, d.ad_group_id, d.campaign_id, d.customer_id"); // 按月聚合
|
||||
$dayDataQuery->field([
|
||||
'd.ad_id',
|
||||
'd.month',
|
||||
// ThinkDb::raw("TO_CHAR(d.date, 'YYYY-MM') AS month"), // 格式化为 YYYY-MM 格式
|
||||
ThinkDb::raw('SUM(d.cost_micros) / 1000000 AS total_spend'),
|
||||
ThinkDb::raw('SUM(d.conversions_value) AS total_conversions_value'),
|
||||
ThinkDb::raw('SUM(d.conversions) AS total_conversions'),
|
||||
ThinkDb::raw('SUM(d.impressions) AS total_impressions'),
|
||||
ThinkDb::raw('SUM(d.clicks) AS total_clicks')
|
||||
]);
|
||||
} else {
|
||||
$dayDataQuery->group('d.ad_id,d.ad_name, d.ad_resource_name, d.ad_group_id, d.campaign_id, d.customer_id'); // 按 ad_id 聚合
|
||||
$dayDataQuery->field([
|
||||
'd.ad_id',
|
||||
ThinkDb::raw('SUM(d.cost_micros) / 1000000 AS total_spend'),
|
||||
ThinkDb::raw('SUM(d.conversions_value) AS total_conversions_value'),
|
||||
ThinkDb::raw('SUM(d.conversions) AS total_conversions'),
|
||||
ThinkDb::raw('SUM(d.impressions) AS total_impressions'),
|
||||
ThinkDb::raw('SUM(d.clicks) AS total_clicks')
|
||||
]);
|
||||
}
|
||||
|
||||
// 获取聚合数据,不需要再传递字段给 select()
|
||||
$aggregatedData = $dayDataQuery->select();
|
||||
// dump($aggregatedData);return($aggregatedData);
|
||||
|
||||
// 3. 获取与 ad_id 关联的 asset_id 以及相关数据
|
||||
$assetRelationsQuery = AssetRelation::whereIn('ad_id', $adIds)
|
||||
->whereBetween('date', [$startDate, $endDate]) // 加上 AssetRelation 的 date 过滤
|
||||
->field(['asset_id', 'ad_id'])->select();
|
||||
// dump($assetRelationsQuery);return($assetRelationsQuery);
|
||||
// 4. 汇总每个 asset_id 下的所有 ad_id 的聚合数据
|
||||
$assetSummaryData = [];
|
||||
|
||||
foreach ($assetRelationsQuery as $assetRelation) {
|
||||
// 从聚合数据中找到当前 ad_id 的相关数据
|
||||
// $adStats = $aggregatedData->where('ad_id', $assetRelation->ad_id)->first();
|
||||
// 获取该 ad_id 的所有聚合数据(可能有多条记录)
|
||||
$adStatsCollection = $aggregatedData->where('ad_id', $assetRelation->ad_id);
|
||||
// dump($adStatsCollection);return($adStatsCollection);
|
||||
if (!$adStatsCollection->isEmpty()) {
|
||||
// 如果该 ad_id 有对应的聚合数据,初始化资产汇总数据
|
||||
if (!isset($assetSummaryData[$assetRelation->asset_id])) {
|
||||
// 获取 asset 相关信息,通过模型查询 Asset
|
||||
$asset = Asset::find($assetRelation->asset_id); // 根据 asset_id 查找对应的 Asset 数据
|
||||
|
||||
$assetSummaryData[$assetRelation->asset_id] = [
|
||||
'asset_id' => $assetRelation->asset_id,
|
||||
'asset_name' => '-', // 获取 asset_name
|
||||
'asset_type' => 0, // 获取 asset_type
|
||||
'asset_url' => '-', // 获取 asset_url
|
||||
'total_spend' => 0,
|
||||
'total_conversions_value' => 0,
|
||||
'total_conversions' => 0,
|
||||
'total_impressions' => 0,
|
||||
'ad_count' => 0,
|
||||
'monthly_data' => [], // 按月存储数据
|
||||
];
|
||||
}
|
||||
|
||||
// 遍历该 ad_id 所有的统计数据
|
||||
foreach ($adStatsCollection as $adStats) {
|
||||
// 获取当前月份
|
||||
if ($isSameMonth) {
|
||||
$month = $currentMonth; // 格式化为 YYYY-MM
|
||||
} else {
|
||||
$month = $adStats->month; // 格式化日期为 'YYYY-MM'
|
||||
}
|
||||
|
||||
// 累加该 ad_id 的统计数据到对应的 asset_id 汇总
|
||||
$assetSummaryData[$assetRelation->asset_id]['asset_name'] = $asset->asset_name;
|
||||
$assetSummaryData[$assetRelation->asset_id]['asset_type'] = $asset->asset_type;
|
||||
$assetSummaryData[$assetRelation->asset_id]['asset_url'] = $asset->asset_url;
|
||||
$assetSummaryData[$assetRelation->asset_id]['total_spend'] += $adStats->total_spend;
|
||||
$assetSummaryData[$assetRelation->asset_id]['total_conversions_value'] += $adStats->total_conversions_value;
|
||||
$assetSummaryData[$assetRelation->asset_id]['total_conversions'] += $adStats->total_conversions;
|
||||
$assetSummaryData[$assetRelation->asset_id]['total_impressions'] += $adStats->total_impressions;
|
||||
$assetSummaryData[$assetRelation->asset_id]['ad'][] = $adStats->ad_id; // 存储 ad_id下一步统计数量
|
||||
|
||||
// 按月分开存储每个月的 spend 和 ROAS
|
||||
if (!isset($assetSummaryData[$assetRelation->asset_id]['monthly_data'][$month])) {
|
||||
$assetSummaryData[$assetRelation->asset_id]['monthly_data'][$month] = [
|
||||
'month' => $month,
|
||||
'spend' => 0,
|
||||
'conversions_value' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
// 累加每个月的数据
|
||||
$assetSummaryData[$assetRelation->asset_id]['monthly_data'][$month]['spend'] += $adStats->total_spend;
|
||||
$assetSummaryData[$assetRelation->asset_id]['monthly_data'][$month]['conversions_value'] += $adStats->total_conversions_value; // 避免除以零
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 格式化输出数据
|
||||
// 生成最终输出的数据
|
||||
$resultData = [];
|
||||
$chat_data = [];
|
||||
foreach ($assetSummaryData as $assetId => $data) {
|
||||
// 计算 ROAS
|
||||
$roas = $data['total_spend'] ? ($data['total_conversions_value'] / $data['total_spend']) * 100 : 0;
|
||||
|
||||
// 合并月度数据到总数据
|
||||
$resultData[] = [
|
||||
'creative_id' => $assetId,
|
||||
'creative' => $data['asset_name'],
|
||||
'creative_type' => $data['asset_type'],
|
||||
'creative_url' => $data['asset_url'],
|
||||
'spend' => number_format($data['total_spend'], 2),
|
||||
'purchase_value' => '-',
|
||||
'roas' => number_format($roas, 2) . '%',
|
||||
'cpa' => '-',
|
||||
'cpc_link_click' => '-',
|
||||
'cpm' => '-',
|
||||
'cpc_all' => '-',
|
||||
'aov' => '-',
|
||||
'click_to_atc_ratio' => '-',
|
||||
'atc_to_purchase_ratio' => '-',
|
||||
'purchases' => '-',
|
||||
'first_frame_retention' => '-',
|
||||
'thumbstop' => '-',
|
||||
'ctr_outbound' => '-',
|
||||
'click_to_purchase' => '-',
|
||||
'ctr_all' => '-',
|
||||
'video_plays_25_rate' => '-',
|
||||
'video_plays_50_rate' => '-',
|
||||
'video_plays_75_rate' => '-',
|
||||
'video_plays_100_rate' => '-',
|
||||
'hold_rate' => '-',
|
||||
'total_conversions_value' => number_format($data['total_conversions_value'], 2),
|
||||
'total_conversions' => $data['total_conversions'],
|
||||
'total_impressions' => $data['total_impressions'],
|
||||
'ad_count' => count($data['ad']),
|
||||
|
||||
// 'monthly_data' => $data['monthly_data'], // 合并月度数据
|
||||
];
|
||||
|
||||
// 计算每个月的汇总数据,用于 chat_data
|
||||
foreach ($data['monthly_data'] as $month => $monthlyData) {
|
||||
// 如果 chat_data 中已有该月的数据,则累加
|
||||
if (!isset($chat_data[$month])) {
|
||||
$chat_data[$month] = [
|
||||
'month' => $month,
|
||||
'total_spend' => 0,
|
||||
'total_conversions_value' => 0,
|
||||
'roas' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
// 累加该月的 spend 和 conversions_value
|
||||
$chat_data[$month]['total_spend'] += $monthlyData['spend'];
|
||||
$chat_data[$month]['total_conversions_value'] += $monthlyData['conversions_value'];
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 计算每个月的总 ROAS,ROAS = 总的转换值 / 总的支出
|
||||
foreach ($chat_data as $month => $data) {
|
||||
// 计算 ROAS
|
||||
$totalSpend = $data['total_spend'];
|
||||
$totalConversionsValue = $data['total_conversions_value'];
|
||||
|
||||
// 如果有支出数据,计算 ROAS
|
||||
$chat_data[$month]['roas'] = $totalSpend ? ($totalConversionsValue / $totalSpend) * 100 : 0;
|
||||
// 格式化 ROAS 为百分比
|
||||
$chat_data[$month]['roas'] = number_format($chat_data[$month]['roas'], 2) . '%';
|
||||
}
|
||||
|
||||
// 返回分页数据
|
||||
$resultDataPaginated = array_slice($resultData, ($page - 1) * $pageSize, $pageSize);
|
||||
|
||||
return [
|
||||
'data' => $resultDataPaginated,
|
||||
'chat_1_data' => array_values($chat_data), // 返回按月汇总的 chat_data
|
||||
'total' => count($resultData),
|
||||
'current_page' => (int)$page,
|
||||
'last_page' => ceil(count($resultData) / $pageSize),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,6 +63,11 @@ Route::group('/googleads', function () {
|
||||
})->middleware([
|
||||
app\middleware\OauthCheck::class,
|
||||
]);
|
||||
Route::group('/asset', function () {
|
||||
Route::post('/list', [AdController::class, 'listAssets']);
|
||||
})->middleware([
|
||||
app\middleware\OauthCheck::class,
|
||||
]);
|
||||
|
||||
Route::group('/auth', function () {
|
||||
Route::get('/code', [OAuthController::class, 'getAuthCode']);
|
||||
|
Loading…
Reference in New Issue
Block a user