Dashboard meta、google、tiktok的看板数据 更新1
This commit is contained in:
parent
03aa4c73ab
commit
5d9ca56b02
@ -8,6 +8,7 @@ use app\service\GoogleAdsGroupService;
|
||||
|
||||
//use app\service\GoogleAdsReportService;
|
||||
use app\service\AdsInsightService;
|
||||
use app\service\AdsDashboardService;
|
||||
use app\service\LandingUrlInsightService;
|
||||
use app\service\GoogleOAuthService;
|
||||
use app\service\BpsAdAccountService;
|
||||
@ -25,6 +26,13 @@ class BpsAdController
|
||||
*/
|
||||
private $adsInsightService;
|
||||
|
||||
/**
|
||||
* /**
|
||||
* @Inject
|
||||
* @var AdsDashboardService
|
||||
*/
|
||||
private $adsDashboardService;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
* @var LandingUrlInsightService
|
||||
@ -85,7 +93,7 @@ class BpsAdController
|
||||
// } else {
|
||||
// $ad_data_count = [];
|
||||
// }
|
||||
// 返回结果
|
||||
// 返回结果
|
||||
return $this->successResponse($ad_data_count, $request);
|
||||
}
|
||||
|
||||
@ -100,8 +108,8 @@ class BpsAdController
|
||||
$keyword = $options['conditions']['keyword'] ?? ''; // 关键字搜索
|
||||
$platformType = $options['conditions']['platformType'] ?? 0; // 平台类型
|
||||
// $status = $options['conditions']['status'] ?? 0; // 平台类型
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
// $dateRange = 'Last Week'; // 默认日期范围
|
||||
|
||||
// 根据 platformType 获取广告账户
|
||||
@ -371,7 +379,7 @@ class BpsAdController
|
||||
);
|
||||
}
|
||||
|
||||
public function exportAccountsToExcel(Request $request)
|
||||
public function exportAccountsToExcel(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
$options['jwtClaims'] = $request->jwtClaims;
|
||||
@ -382,8 +390,8 @@ class BpsAdController
|
||||
$keyword = $options['conditions']['keyword'] ?? ''; // 关键字搜索
|
||||
$platformType = $options['conditions']['platformType'] ?? 0; // 关键字搜索
|
||||
// $status = $options['conditions']['status'] ?? 0; // 平台类型
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
// $dateRange = 'Last Week'; // 默认日期范围
|
||||
// 根据 platformType 获取广告账户
|
||||
if ($platformType === 1) {
|
||||
@ -424,7 +432,7 @@ class BpsAdController
|
||||
);
|
||||
}
|
||||
|
||||
public function exportCreativesToExcel(Request $request)
|
||||
public function exportCreativesToExcel(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
$options['jwtClaims'] = $request->jwtClaims;
|
||||
@ -435,8 +443,8 @@ class BpsAdController
|
||||
$keyword = $options['conditions']['keyword'] ?? ''; // 关键字搜索
|
||||
$platformType = $options['conditions']['platformType'] ?? 0; // 关键字搜索
|
||||
// $status = $options['conditions']['status'] ?? 0; // 平台类型
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
// $dateRange = 'Last Week'; // 默认日期范围
|
||||
// 根据 platformType 获取广告账户
|
||||
if ($platformType === 1) {
|
||||
@ -530,6 +538,7 @@ class BpsAdController
|
||||
$status
|
||||
);
|
||||
}
|
||||
|
||||
public function exportAdsToExcel(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
@ -810,6 +819,41 @@ class BpsAdController
|
||||
return $this->successResponse($result, $request);
|
||||
}
|
||||
|
||||
public function listCards(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
$options['jwtClaims'] = $request->jwtClaims;
|
||||
|
||||
// 获取请求参数
|
||||
$cycle = $options['conditions']['cycle'] ?? 'today'; //默认today Today 1 Yesterday 2 This Month 3 This Year 4 Custom 5
|
||||
// $platformType = $options['conditions']['platformType'] ?? 0; // 平台类型
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
// $dateRange = 'Last Week'; // 默认日期范围
|
||||
|
||||
// TODO: 匹配jwt的商户id还是登录用户id
|
||||
$accounts = $this->bpsAdAccountService->getAllAdAccounts(['uid' => $options['jwtClaims']['uid']]);
|
||||
|
||||
|
||||
if (empty($accounts)) {
|
||||
return $this->successResponse(['data' => []], $request);
|
||||
}
|
||||
|
||||
// 获取客户ID数组
|
||||
$accountIds = array_unique(array_column($accounts, 'account_id'));
|
||||
// dump($accountIds);
|
||||
// 调用 Service 层查询广告组列表
|
||||
$result = $this->adsDashboardService->getAdCycleCard(
|
||||
$accountIds, // 客户 ID 数组
|
||||
$cycle, // 页码
|
||||
$startDate, // 开始日期
|
||||
$endDate // 结束日期
|
||||
);
|
||||
|
||||
// 返回结果
|
||||
return $this->successResponse($result, $request);
|
||||
}
|
||||
|
||||
|
||||
// 可以加入一些公共方法
|
||||
protected function successResponse($data, Request $request): Response
|
||||
|
275
app/service/AdsDashboardService.php
Normal file
275
app/service/AdsDashboardService.php
Normal file
@ -0,0 +1,275 @@
|
||||
<?php
|
||||
|
||||
namespace app\service;
|
||||
|
||||
|
||||
use app\model\BpsAdInsight;
|
||||
|
||||
|
||||
class AdsDashboardService
|
||||
{
|
||||
public function getAdCycleCard($customerIds, $cycle, $startDate = null, $endDate = null)
|
||||
{
|
||||
|
||||
// 将 Y-m-d 格式的日期转换为纯数字格式
|
||||
$startDateNumeric = $startDate ? str_replace('-', '', $startDate) : null;
|
||||
$endDateNumeric = $endDate ? str_replace('-', '', $endDate) : null;
|
||||
|
||||
// 获取当前周期的数据
|
||||
$currentData = $this->getAdcycleInsight($customerIds, $cycle, $startDateNumeric, $endDateNumeric);
|
||||
return $currentData;
|
||||
|
||||
// 计算前一天的日期
|
||||
// $previousStartDate = $startDate ?
|
||||
// (new DateTime($startDate))->modify('-1 day')->format('Ymd') :
|
||||
// null;
|
||||
//
|
||||
// $previousEndDate = $endDate ?
|
||||
// (new DateTime($endDate))->modify('-1 day')->format('Ymd') :
|
||||
// null;
|
||||
|
||||
// 获取前一天周期的数据
|
||||
// $lastData = $this->getAdcycleInsight($customerIds, $cycle, $previousStartDate, $previousEndDate);
|
||||
|
||||
}
|
||||
|
||||
public function getAdcycleInsight($customerIds, $cycle, $startDate = null, $endDate = null)
|
||||
{
|
||||
// 1. 查询全部数据集
|
||||
$adcycleDataQuery = BpsAdInsight::alias('d');
|
||||
//dump($customerIds);
|
||||
// 2. 客户 ID 过滤(如果提供了)
|
||||
if (!empty($customerIds)) {
|
||||
$adcycleDataQuery->whereIn('d.account_id', $customerIds);
|
||||
} else {
|
||||
return [
|
||||
'data' => [
|
||||
'meta' => [
|
||||
'meta_ads' => '-',
|
||||
'roas' => '-',
|
||||
'cpc' => '-',
|
||||
'cpm' => '-',
|
||||
'meta_purchases' => '-',
|
||||
'web_purchases' => '-',
|
||||
'purchases' => '-',
|
||||
'meta_conversion_value' => '-',
|
||||
'web_conversion_value' => '-',
|
||||
'conversion_value' => '-',
|
||||
'cpoc' => '-',
|
||||
'ctr' => '-',
|
||||
'revenue_per_link_click' => '-',
|
||||
'cpa' => '-',
|
||||
],
|
||||
'google' => [
|
||||
'google_ads' => '-',
|
||||
'conversion_value' => '-',
|
||||
'roas' => '-',
|
||||
'conversions' => '-',
|
||||
'ctr' => '-',
|
||||
'cpa' => '-',
|
||||
'cpm' => '-',
|
||||
'clicks' => '-',
|
||||
'impressions' => '-',
|
||||
'all_conversions_value' => '-',
|
||||
'all_roas' => '-',
|
||||
'all_conversions' => '-',
|
||||
'all_cpa' => '-',
|
||||
],
|
||||
'tiktok' => [
|
||||
'tiktok_ads' => '-',
|
||||
'roas' => '-',
|
||||
'impressions' => '-',
|
||||
'cpm' => '-',
|
||||
'cpc' => '-',
|
||||
'ctr' => '-',
|
||||
'cpa' => '-',
|
||||
'tiktok_shop_conversions' => '-',
|
||||
'tiktok_shop_conversion_value' => '-',
|
||||
'conversion_value' => '-',
|
||||
'web_conversion_value' => '-',
|
||||
'purchases' => '-',
|
||||
'web_purchases' => '-',
|
||||
'tiktok_gmv_max_ads' => '-',
|
||||
]
|
||||
]
|
||||
|
||||
];
|
||||
}
|
||||
// 3. 时间范围筛选
|
||||
if ($startDate && $endDate) {
|
||||
$adcycleDataQuery->whereBetween('d.date', [$startDate, $endDate]);
|
||||
}
|
||||
|
||||
// 4. 获取数据并按平台和日期聚合
|
||||
$adcycleData = $adcycleDataQuery->field(
|
||||
'd.platform,
|
||||
COALESCE(SUM(d.assisted_purchases), 0) as assisted_purchases,
|
||||
COALESCE(SUM(d.last_clicked_purchases), 0) as last_clicked_purchases,
|
||||
COALESCE(SUM(d.clicks), 0) as clicks,
|
||||
COALESCE(SUM(d.spend) / 1000000, 0) as spend,
|
||||
COALESCE(SUM(d.impressions), 0) as impressions,
|
||||
COALESCE(SUM(d.adds_to_cart), 0) as adds_to_cart,
|
||||
COALESCE(SUM(d.cost_per_atc), 0) as cost_per_atc,
|
||||
COALESCE(SUM(d.purchases), 0) as purchases,
|
||||
COALESCE(SUM(d.purchases_value) / 1000000, 0) as purchases_value,
|
||||
COALESCE(SUM(d.revenue) / 1000000, 0) as revenue,
|
||||
COALESCE(SUM(d.total_cost) / 1000000, 0) as total_cost'
|
||||
)
|
||||
->group('d.platform, d.date') // 按平台和日期进行分组
|
||||
->select();
|
||||
|
||||
// 定义字段映射关系
|
||||
$fieldMapping = [
|
||||
'meta' => [
|
||||
'meta_ads' => 'spend', // 示例映射
|
||||
'roas' => 'roas',
|
||||
'cpc' => 'cpc',
|
||||
'cpm' => 'cpm',
|
||||
'meta_purchases' => 'purchases',
|
||||
'web_purchases' => 'purchases',
|
||||
'purchases' => 'purchases',
|
||||
'meta_conversion_value' => 'purchases_value',
|
||||
'web_conversion_value' => 'purchases_value',
|
||||
'conversion_value' => 'purchases_value',
|
||||
'cpoc' => 'cost_per_atc',
|
||||
'ctr' => 'ctr',
|
||||
'revenue_per_link_click' => 'revenue_per_link_click',
|
||||
'cpa' => 'cpa',
|
||||
],
|
||||
'google' => [
|
||||
'google_ads' => 'spend', // 示例映射
|
||||
'conversion_value' => 'purchases_value',
|
||||
'roas' => 'roas',
|
||||
'conversions' => 'purchases',
|
||||
'ctr' => 'ctr',
|
||||
'cpa' => 'cpa',
|
||||
'cpm' => 'cpm',
|
||||
'clicks' => 'clicks',
|
||||
'impressions' => 'impressions',
|
||||
'all_conversions_value' => 'purchases_value',
|
||||
'all_roas' => 'roas',
|
||||
'all_conversions' => 'purchases',
|
||||
'all_cpa' => 'cpa',
|
||||
],
|
||||
'tiktok' => [
|
||||
'tiktok_ads' => 'spend', // 示例映射
|
||||
'roas' => 'roas',
|
||||
'impressions' => 'impressions',
|
||||
'cpm' => 'cpm',
|
||||
'cpc' => 'cpc',
|
||||
'ctr' => 'ctr',
|
||||
'cpa' => 'cpa',
|
||||
'tiktok_shop_conversions' => 'purchases',
|
||||
'tiktok_shop_conversion_value' => 'purchases_value',
|
||||
'conversion_value' => 'purchases_value',
|
||||
'web_conversion_value' => 'purchases_value',
|
||||
'purchases' => 'purchases',
|
||||
'web_purchases' => 'purchases',
|
||||
'tiktok_gmv_max_ads' => 'revenue',
|
||||
],
|
||||
];
|
||||
|
||||
// 初始化结果数组
|
||||
$result = [
|
||||
'data' => [
|
||||
'meta' => array_fill_keys(array_keys($fieldMapping['meta']), '-'),
|
||||
'google' => array_fill_keys(array_keys($fieldMapping['google']), '-'),
|
||||
'tiktok' => array_fill_keys(array_keys($fieldMapping['tiktok']), '-'),
|
||||
],
|
||||
];
|
||||
|
||||
// 在 PHP 中计算指标
|
||||
foreach ($adcycleData as $data) {
|
||||
$platform = $data['platform']; // 获取平台类型
|
||||
$spend = (float)$data['spend'];
|
||||
$revenue = (float)$data['revenue'];
|
||||
$totalCost = (float)$data['total_cost'];
|
||||
$impressions = (int)$data['impressions'];
|
||||
$clicks = (int)$data['clicks'];
|
||||
$purchases = (int)$data['purchases'];
|
||||
$purchasesValue = (float)$data['purchases_value'];
|
||||
|
||||
// 计算指标
|
||||
$roas = ($spend == 0) ? 0 : $revenue / $spend;
|
||||
$ctr = ($impressions == 0) ? 0 : $clicks / $impressions;
|
||||
$cpa = ($purchases == 0) ? 0 : $spend / $purchases;
|
||||
$cpm = ($impressions == 0) ? 0 : ($spend * 1000) / $impressions;
|
||||
$cpc = ($clicks == 0) ? 0 : $spend / $clicks;
|
||||
$conversionRate = ($clicks == 0) ? 0 : $purchases / $clicks;
|
||||
$revenuePerLinkClick = ($clicks == 0) ? 0 : $revenue / $clicks;
|
||||
|
||||
// 根据平台类型映射数据
|
||||
$platformKey = match ($platform) {
|
||||
1 => 'meta',
|
||||
2 => 'google',
|
||||
3 => 'tiktok',
|
||||
default => null,
|
||||
};
|
||||
|
||||
if ($platformKey) {
|
||||
foreach ($fieldMapping[$platformKey] as $targetField => $sourceField) {
|
||||
$value = '-';
|
||||
switch ($sourceField) {
|
||||
case 'spend':
|
||||
$value = '$' . number_format($spend, 2);
|
||||
break;
|
||||
case 'revenue':
|
||||
$value = '$' . number_format($revenue, 2);
|
||||
break;
|
||||
case 'total_cost':
|
||||
$value = '$' . number_format($totalCost, 2);
|
||||
break;
|
||||
case 'purchases_value':
|
||||
$value = '$' . number_format($purchasesValue, 2);
|
||||
break;
|
||||
case 'roas':
|
||||
$value = $roas . 'X';
|
||||
break;
|
||||
case 'ctr':
|
||||
$value = number_format($ctr * 100, 2) . '%';
|
||||
break;
|
||||
case 'cpa':
|
||||
$value = '$' . number_format($cpa, 2);
|
||||
break;
|
||||
case 'cpm':
|
||||
$value = '$' . number_format($cpm, 2);
|
||||
break;
|
||||
case 'cpc':
|
||||
$value = '$' . number_format($cpc, 2);
|
||||
break;
|
||||
case 'conversion_rate':
|
||||
$value = $conversionRate;
|
||||
break;
|
||||
case 'revenue_per_link_click':
|
||||
$value = $revenuePerLinkClick;
|
||||
break;
|
||||
case 'purchases':
|
||||
$value = $purchases;
|
||||
break;
|
||||
case 'clicks':
|
||||
$value = $clicks;
|
||||
break;
|
||||
case 'impressions':
|
||||
$value = $impressions;
|
||||
break;
|
||||
default:
|
||||
$value = '-';
|
||||
break;
|
||||
}
|
||||
$result['data'][$platformKey][$targetField] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
// dump(ThinkDb::getLastSql());
|
||||
|
||||
// 5. 处理数据,按照周期进行分组
|
||||
// $processedData = $this->processDataByCycle($adcycleData->toArray(), $cycle);
|
||||
|
||||
// 6. 返回处理后的数据
|
||||
// return $adcycleData;
|
||||
}
|
||||
|
||||
}
|
@ -89,6 +89,12 @@ Route::group('/marketing', function () {
|
||||
app\middleware\JwtLocal::class,
|
||||
app\middleware\OauthThirdCheck::class,
|
||||
]);
|
||||
Route::group('/dashboard', function () {
|
||||
Route::post('/ad_card', [BpsAdController::class, 'listCards']);
|
||||
})->middleware([
|
||||
app\middleware\JwtLocal::class,
|
||||
app\middleware\OauthThirdCheck::class,
|
||||
]);
|
||||
Route::group('/landing', function () {
|
||||
Route::post('/list', [BpsAdController::class, 'listLandingUrls']);
|
||||
// Route::post('/export', [BpsAdController::class, 'exportLandingUrlsToExcel']);
|
||||
|
Loading…
Reference in New Issue
Block a user