1639 lines
65 KiB
PHP
1639 lines
65 KiB
PHP
<?php
|
|
namespace App\ThirdParty\facebook_api;
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
error_reporting(E_ALL & ~E_NOTICE);
|
|
ini_set("display_errors", 1);
|
|
//ini_set('max_execution_time', 1800);
|
|
set_time_limit(0);
|
|
ini_set('memory_limit', '-1');
|
|
|
|
require_once __DIR__ . '/vendor/autoload.php';
|
|
|
|
use App\ThirdParty\facebook_api\FBDB;
|
|
use CodeIgniter\CLI\CLI;
|
|
|
|
use JanuSoftware\Facebook\Facebook;
|
|
use FacebookAds\Api;
|
|
use FacebookAds\Object\AdAccount;
|
|
use FacebookAds\Object\Campaign;
|
|
use FacebookAds\Object\Fields\CampaignFields;
|
|
use FacebookAds\Object\AdSet;
|
|
use FacebookAds\Object\Fields\AdSetFields;
|
|
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
|
|
use FacebookAds\Object\Fields\AdCreativeFields;
|
|
use FacebookAds\Object\Ad;
|
|
use FacebookAds\Object\Fields\AdFields;
|
|
use FacebookAds\Object\Fields\AdsInsightsFields;
|
|
use FacebookAds\Object\Values\AdsInsightsLevelValues;
|
|
use FacebookAds\Object\Values\AdsInsightsDatePresetValues;
|
|
use FacebookAds\Object\Values\AdsInsightsBreakdownsValues;
|
|
use FacebookAds\Object\Fields\LeadFields;
|
|
use DateTime;
|
|
use Exception;
|
|
use App\Libraries\slack_api\SlackChat;
|
|
|
|
class ZenithFB
|
|
{
|
|
private $app_id; //(주)케어랩스 //'318448081868728'; // 열혈패밀리_ver3
|
|
private $app_secret; //'881a2a6c6edcc9a5291e829278cb91e2';
|
|
private $access_token;
|
|
private $longLivedAccessToken;
|
|
private $db;
|
|
private $fb;
|
|
private $business_id_list;
|
|
private $business_id;
|
|
private $account_id;
|
|
private $campaign_id;
|
|
private $adset_id;
|
|
private $ad_id;
|
|
private $result_data = [];
|
|
private $account, $campaign, $adset, $ad;
|
|
private $slack, $slackChannel = '광고API';
|
|
|
|
// https://developers.facebook.com/tools/debug/accesstoken
|
|
public function __construct($bs_id = '')
|
|
{
|
|
@set_exception_handler(array($this, 'exception_handler'));
|
|
|
|
try {
|
|
include __DIR__."/config.php";
|
|
$this->app_id = $config['app_id'];
|
|
$this->app_secret = $config['app_secret'];
|
|
$this->access_token = $config['access_token'];
|
|
$this->longLivedAccessToken = $config['longLivedAccessToken'];
|
|
$this->business_id_list = $config['business_id_list'];
|
|
|
|
$this->db = new FBDB();
|
|
$this->access_token = empty($this->access_token) ? "" : (empty($this->longLivedAccessToken) ? $this->access_token : $this->longLivedAccessToken);
|
|
if(empty($this->access_token)) {
|
|
$this->access_token = $this->getAccessToken();
|
|
}
|
|
Api::init($this->app_id, $this->app_secret, $this->access_token, false);
|
|
$this->fb = new Facebook([
|
|
'app_id' => $this->app_id,
|
|
'app_secret' => $this->app_secret,
|
|
'default_access_token' => $this->access_token,
|
|
'default_graph_version' => 'v20.0'
|
|
]);
|
|
$this->business_id = $bs_id ? $bs_id : $this->business_id_list[0];
|
|
$this->slack = new SlackChat();
|
|
} catch (Exception $ex) {
|
|
echo $ex->getMessage();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function getAccessToken()
|
|
{
|
|
$url = "https://graph.facebook.com/oauth/access_token";
|
|
$params = [
|
|
'client_id' => $this->app_id,
|
|
'client_secret' => $this->app_secret,
|
|
'grant_type' => 'client_credentials'
|
|
];
|
|
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($params));
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
|
|
$response = curl_exec($ch);
|
|
if (curl_errno($ch)) {
|
|
throw new Exception(curl_error($ch));
|
|
}
|
|
curl_close($ch);
|
|
|
|
$data = json_decode($response, true);
|
|
if (isset($data['access_token'])) {
|
|
return $data['access_token'];
|
|
} else {
|
|
throw new Exception("Error getting access token: " . $response);
|
|
}
|
|
}
|
|
|
|
// 일반 엑세스 토큰을 연장시킴
|
|
public function getLongLivedAccessToken()
|
|
{
|
|
try { //EAAEhoHjMl7gBAJVuAZCygZCHp11NFWNmf6Hng4KSCDBZCEakZC7yEkZAnAkqvXw9wSAqWX3Qg20r0rzoQORglAp1RMNdqHEeQ4Gy1GZCBlVaDIwvI4BiQzBNavFDRWk49adliwGauowZCc6j3DoMKyDuenoSa0iBVHh9t2hMJ35Pfd8Y1XcHRBy
|
|
$oAuth2Client = $this->fb->getOAuth2Client();
|
|
$longLivedAccessToken = $oAuth2Client->getLongLivedAccessToken($this->access_token);
|
|
$this->access_token = $longLivedAccessToken;
|
|
CLI::write("longLivedAccessToken at ". CLI::color($longLivedAccessToken, "white"), "yellow");
|
|
|
|
} catch (Exception $ex) {
|
|
echo $ex->getMessage();
|
|
}
|
|
}
|
|
|
|
// 페이스북 광고 계정 목록
|
|
/* 1 = ACTIVE
|
|
2 = DISABLED
|
|
101 = CLOSED */
|
|
|
|
public function getFBAccounts()
|
|
{
|
|
try {
|
|
$response = $this->fb->get(
|
|
'/' . $this->business_id . '/owned_ad_accounts?fields=account_id,name,account_status,disable_reason,funding_source_details,adspixels{id,name}&limit=20',
|
|
$this->access_token
|
|
);
|
|
$edges = $response->getGraphEdge();
|
|
$results = [];
|
|
|
|
do {
|
|
foreach ($edges as $account) {
|
|
$account = $account->asArray();
|
|
$pixel_id = 'NULL';
|
|
$funding_source = 'NULL';
|
|
if (isset($account['adspixels'])) {
|
|
$pixel_id = $account['adspixels'][0]['id'];
|
|
}
|
|
if (isset($account['funding_source_details']) && isset($account['funding_source_details']['display_string'])) {
|
|
$funding_source = $account['funding_source_details']['display_string'];
|
|
}
|
|
array_push($results, [$this->business_id, $account['account_id'], $account['name'], $funding_source, $account['account_status'], $account['disable_reason'], $pixel_id]);
|
|
}
|
|
} while ($edges = $this->fb->next($edges));
|
|
|
|
return $results;
|
|
} catch (Exception $ex) {
|
|
$msgs = [
|
|
'channel' => '광고API',
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고계정] 수신 오류 : " . $ex->getMessage(),
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
}
|
|
|
|
// 비지니스 설정
|
|
public function setBusinessId($bs_id = null) {
|
|
if(!is_null($bs_id)) $this->business_id = $bs_id;
|
|
}
|
|
|
|
// 광고 계정 설정
|
|
function setAdAccount($account_id)
|
|
{
|
|
$this->account_id = "act_" . $account_id;
|
|
$this->account = new AdAccount($this->account_id);
|
|
}
|
|
|
|
// 캠페인 ID 설정
|
|
function setCampaignId($campaign_id)
|
|
{
|
|
$this->campaign_id = $campaign_id;
|
|
$this->campaign = new Campaign($this->campaign_id);
|
|
}
|
|
|
|
// 광고세트 ID 설정
|
|
function setAdsetId($adset_id)
|
|
{
|
|
$this->adset_id = $adset_id;
|
|
$this->adset = new AdSet($this->adset_id);
|
|
}
|
|
|
|
// 광고 ID 설정
|
|
function setAdId($adset_id)
|
|
{
|
|
$this->ad_id = $adset_id;
|
|
$this->ad = new Ad($this->ad_id);
|
|
}
|
|
|
|
// 인사이트 비동기 호출
|
|
public function getAsyncInsights($all = "false", $date = null, $edate = null, $account_id = null)
|
|
{
|
|
try {
|
|
$startTime = microtime(true); // 시작 시간 기록
|
|
|
|
$params = [
|
|
'date_preset' => AdsInsightsDatePresetValues::TODAY,
|
|
'level' => AdsInsightsLevelValues::AD,
|
|
'breakdowns' => AdsInsightsBreakdownsValues::HOURLY_STATS_AGGREGATED_BY_AUDIENCE_TIME_ZONE,
|
|
'filtering' => [
|
|
// [
|
|
// 'field' => 'ad.impressions',
|
|
// 'operator' => 'GREATER_THAN',
|
|
// 'value' => 0
|
|
// ],
|
|
// [
|
|
// 'field' => 'ad.spend',
|
|
// 'operator' => 'GREATER_THAN',
|
|
// 'value' => 0
|
|
// ],
|
|
// [
|
|
// 'field' => 'ad.effective_status',
|
|
// 'operator' => 'IN',
|
|
// 'value' => ['ACTIVE', 'ADSET_PAUSED', 'ARCHIVED', 'CAMPAIGN_PAUSED', 'DELETED', 'DISAPPROVED', 'IN_PROCESS', 'PAUSED', 'PENDING_BILLING_INFO', 'PENDING_REVIEW', 'PREAPPROVED', 'WITH_ISSUES']
|
|
// ]
|
|
],
|
|
'fields' => [
|
|
AdsInsightsFields::ACCOUNT_ID,
|
|
AdsInsightsFields::CAMPAIGN_ID,
|
|
AdsInsightsFields::CAMPAIGN_NAME,
|
|
AdsInsightsFields::ADSET_ID,
|
|
AdsInsightsFields::ADSET_NAME,
|
|
AdsInsightsFields::AD_ID,
|
|
AdsInsightsFields::AD_NAME,
|
|
AdsInsightsFields::DATE_START,
|
|
AdsInsightsFields::DATE_STOP,
|
|
AdsInsightsFields::IMPRESSIONS,
|
|
AdsInsightsFields::CLICKS,
|
|
AdsInsightsFields::INLINE_LINK_CLICKS,
|
|
AdsInsightsFields::SPEND
|
|
]
|
|
];
|
|
if (!is_null($date)) {
|
|
if (is_null($edate)) {
|
|
$edate = $date;
|
|
}
|
|
$params['time_range'] = ['since' => $date, 'until' => $edate];
|
|
unset($params['date_preset']);
|
|
}
|
|
if(!is_null($account_id)) {
|
|
$accounts[]['ad_account_id'] = $account_id;
|
|
$total = 1;
|
|
} else {
|
|
$account_id = $this->db->getAdAccounts(true);
|
|
$accounts = $account_id->getResultArray();
|
|
$total = $account_id->getNumRows();
|
|
}
|
|
$step = 1;
|
|
CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 계정에 대한 광고인사이트 수신을 시작합니다.", "light_red");
|
|
$return = [];
|
|
foreach ($accounts as $row) {
|
|
$result = [];
|
|
$this->setAdAccount($row['ad_account_id']);
|
|
$async_job = $this->account->getInsightsAsync([], $params);
|
|
$getSelf = $async_job->getSelf();
|
|
$count = 0;
|
|
$continue = false;
|
|
while (!$getSelf->isComplete() && !$continue) {
|
|
$getSelf = $async_job->getSelf();
|
|
if ($count > 100 && !$getSelf->isComplete()) {
|
|
ob_flush(); flush(); sleep(1);
|
|
$continue = true;
|
|
}
|
|
$count++;
|
|
}
|
|
CLI::showProgress($step++, $total);
|
|
// if ($continue) continue;
|
|
$insights = $getSelf->getInsights();
|
|
$getResponse = $insights->getResponse();
|
|
$response = $getResponse->getContent();
|
|
$result = array_merge($result, $response['data']);
|
|
if (isset($response['paging'])) {
|
|
$url = isset($response['paging']['next']) ? $response['paging']['next'] : false;
|
|
while ($url) {
|
|
$data = $this->getFBRequest_CURL($url);
|
|
if (!is_null($data) && isset($data['data'])) $result = array_merge($result, $data['data']);
|
|
$url = isset($data['paging']['next']) ? $data['paging']['next'] : false;
|
|
}
|
|
}
|
|
|
|
$this->db->insertAsyncInsights($result);
|
|
$return = array_merge($return, $result);
|
|
}
|
|
$endTime = microtime(true); // 종료 시간 기록
|
|
$executionTime = round($endTime - $startTime, 2); // 실행 시간 계산
|
|
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][인사이트] {$date}~{$edate} 수신 완료 (실행 시간: {$executionTime}초)",
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
if ($all == "true") {
|
|
$this->updateAds($return);
|
|
$this->updateAdCreatives($return);
|
|
$this->updateAdsets($return);
|
|
$this->updateCampaigns($return);
|
|
}
|
|
|
|
return $return;
|
|
} catch (Exception $ex) {
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][인사이트] {$date}~{$edate} 수신 오류 : " . $ex->getMessage(),
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
}
|
|
|
|
public function updateAllByAccounts() {
|
|
foreach($this->business_id_list as $bs_id) {
|
|
self::setBusinessId($bs_id);
|
|
CLI::write("[".date("Y-m-d H:i:s")."]"."{$bs_id}비지니스 업데이트 시작", "white", "magenta");
|
|
self::updateAllByAccount();
|
|
CLI::write("[".date("Y-m-d H:i:s")."]"."{$bs_id}비지니스 업데이트 종료", "white", "magenta");
|
|
}
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북]비지니스별 캠페인/광고그룹/광고 정보 수신 완료",
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
|
|
public function updateAllByAccount($bs_id=null) {
|
|
try {
|
|
if(is_null($bs_id)) $bs_id = $this->business_id;
|
|
$account_id = $this->db->getAdAccounts(true, " AND business_id = '{$bs_id}'");
|
|
$accounts = $account_id->getResultArray();
|
|
$total = $account_id->getNumRows();
|
|
$step = 1;
|
|
CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 계정에 대한 광고데이터 수신을 시작합니다.", "light_red");
|
|
$result = [];
|
|
$campaigns_fields = implode(',', [ CampaignFields::ID, CampaignFields::NAME, CampaignFields::ACCOUNT_ID, CampaignFields::DAILY_BUDGET, CampaignFields::BUDGET_REMAINING, CampaignFields::BUDGET_REBALANCE_FLAG, CampaignFields::CAN_USE_SPEND_CAP, CampaignFields::SPEND_CAP, CampaignFields::OBJECTIVE, CampaignFields::EFFECTIVE_STATUS, CampaignFields::STATUS, CampaignFields::START_TIME, CampaignFields::CREATED_TIME, CampaignFields::UPDATED_TIME ]);
|
|
$adsets_fields = implode(',', [ AdSetFields::ID, AdSetFields::NAME, AdSetFields::CAMPAIGN_ID, AdSetFields::EFFECTIVE_STATUS, AdSetFields::STATUS, AdSetFields::LEARNING_STAGE_INFO, AdSetFields::START_TIME, AdSetFields::UPDATED_TIME, AdSetFields::CREATED_TIME, AdSetFields::DAILY_BUDGET, AdSetFields::LIFETIME_BUDGET, AdSetFields::BUDGET_REMAINING ]);
|
|
$ads_fields = implode(',', [ AdFields::ID, AdFields::NAME, AdFields::ADSET_ID, AdFields::EFFECTIVE_STATUS, AdFields::STATUS, AdFields::UPDATED_TIME, AdFields::CREATED_TIME, AdFields::TRACKING_SPECS, AdFields::CONVERSION_SPECS ]);
|
|
$adcreatives_fields = implode(',', [ AdCreativeFields::ID, AdCreativeFields::BODY, AdCreativeFields::OBJECT_TYPE, AdCreativeFields::OBJECT_URL, AdCreativeFields::THUMBNAIL_URL, AdCreativeFields::IMAGE_FILE, AdCreativeFields::IMAGE_URL, AdCreativeFields::CALL_TO_ACTION_TYPE, AdCreativeFields::OBJECT_STORY_SPEC ]);
|
|
foreach($accounts as $account) {
|
|
CLI::showProgress($step++, $total);
|
|
$response = $this->fb->get(
|
|
"/act_{$account['ad_account_id']}?fields=id,name,campaigns{{$campaigns_fields},adsets{{$adsets_fields},ads{{$ads_fields},adcreatives{{$adcreatives_fields}}}}}",
|
|
$this->access_token
|
|
);
|
|
$data = $response->getDecodedBody();
|
|
$results = [];
|
|
$campaigns = $data['campaigns']['data'] ?? [];
|
|
foreach ($campaigns as $campaign) {
|
|
$adsets = $campaign['adsets']['data'] ?? [];
|
|
foreach ($adsets as $adset) {
|
|
$ads = $adset['ads']['data'] ?? [];
|
|
foreach ($ads as $ad) {
|
|
$adcreatives = $ad['adcreatives']['data'] ?? [];
|
|
foreach ($adcreatives as &$adcreative) {
|
|
$adcreative['ad_id'] = $ad['id'];
|
|
}
|
|
unset($adcreative);
|
|
$this->updateAdcreatives(null, $adcreatives);
|
|
}
|
|
$this->db->updateAds($ads);
|
|
}
|
|
$this->db->updateAdsets($adsets);
|
|
}
|
|
$this->db->updateCampaigns($campaigns);
|
|
}
|
|
} catch (Exception $ex) {
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북] {$bs_id} 캠페인/광고그룹/광고 정보 수신 오류 : " . $ex->getMessage(),
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
}
|
|
|
|
public function updateAdCreatives($data = null, $adcreatives = null)
|
|
{
|
|
try {
|
|
if(is_null($adcreatives)) $adcreatives = $this->getAdCreatives($data);
|
|
|
|
$result = [];
|
|
foreach ($adcreatives as $data) {
|
|
$updatedAdCreative = [
|
|
'adcreative_id' => $data['id'],
|
|
'ad_id' => $data['ad_id'],
|
|
'thumbnail_url' => $data['thumbnail_url'] ?? '',
|
|
'object_type' => $data[AdCreativeFields::OBJECT_TYPE] ?? '',
|
|
];
|
|
$asset_feed_spec = $data[AdCreativeFields::ASSET_FEED_SPEC] ?? [];
|
|
if(isset($asset_feed_spec['call_to_action_types']) && isset($asset_feed_spec['call_to_action_types'][0]))
|
|
$data[AdCreativeFields::CALL_TO_ACTION_TYPE] = $asset_feed_spec['call_to_action_types'][0];
|
|
if (isset($data[AdCreativeFields::CALL_TO_ACTION_TYPE]) && in_array($data[AdCreativeFields::CALL_TO_ACTION_TYPE], ["LEARN_MORE", "APPLY_NOW", "SIGN_UP", "SHOP_NOW"])) {
|
|
$object_story_spec = $data[AdCreativeFields::OBJECT_STORY_SPEC] ?? [];
|
|
$video_data = $object_story_spec[AdCreativeObjectStorySpecFields::VIDEO_DATA] ?? [];
|
|
$link_data = $object_story_spec[AdCreativeObjectStorySpecFields::LINK_DATA] ?? [];
|
|
if(isset($updatedAdCreative['object_type'])){
|
|
switch ($updatedAdCreative['object_type']) {
|
|
case 'SHARE':
|
|
case 'STATUS':
|
|
if (is_array($link_data) && isset($link_data['link'])) { //슬라이드형
|
|
$updatedAdCreative['link'] = $link_data['link'];
|
|
} else if(isset($asset_feed_spec['link_urls']) && isset($asset_feed_spec['link_urls'][0]) && isset($asset_feed_spec['link_urls'][0]['website_url'])) {
|
|
$updatedAdCreative['link'] = $asset_feed_spec['link_urls'][0]['website_url'];
|
|
}
|
|
break;
|
|
case 'VIDEO':
|
|
if (is_array($video_data) && isset($video_data['call_to_action']) && isset($video_data['call_to_action']['value'])) { //비디오
|
|
$updatedAdCreative['link'] = $video_data['call_to_action']['value']['link'];
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (isset($updatedAdCreative['link']) && ($updatedAdCreative['link'] == 'https://fb.me/' || $updatedAdCreative['link'] == 'http://fb.me/'))
|
|
$updatedAdCreative['link'] = '';
|
|
}
|
|
$result[] = $updatedAdCreative;
|
|
}
|
|
$this->db->updateAdCreatives($result);
|
|
return $result;
|
|
} catch (Exception $ex) {
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][소재 정보] 수신 오류 : " . $ex->getMessage(),
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
}
|
|
|
|
public function getAdCreatives($data = null)
|
|
{
|
|
$result = [];
|
|
$params = [
|
|
'thumbnail_width' => 250,
|
|
'thumbnail_height' => 250,
|
|
];
|
|
$fields = [
|
|
AdCreativeFields::ID,
|
|
AdCreativeFields::BODY,
|
|
AdCreativeFields::OBJECT_TYPE,
|
|
AdCreativeFields::OBJECT_URL,
|
|
AdCreativeFields::THUMBNAIL_URL,
|
|
AdCreativeFields::IMAGE_FILE,
|
|
AdCreativeFields::IMAGE_URL,
|
|
AdCreativeFields::CALL_TO_ACTION_TYPE,
|
|
AdCreativeFields::ASSET_FEED_SPEC,
|
|
AdCreativeFields::OBJECT_STORY_SPEC
|
|
];
|
|
if ($data == null) {
|
|
$ad_ids = $this->db->getAdsWithAccount();
|
|
foreach ($ad_ids->getResultArray() as $row) {
|
|
$data[] = $row;
|
|
}
|
|
}
|
|
foreach ($data as $row) {
|
|
if (isset($row['id']))
|
|
$row['ad_id'] = $row['id'];
|
|
$this->setAdId($row['ad_id']);
|
|
$adcrearives = $this->ad->getAdCreatives($fields, $params);
|
|
$response = $adcrearives->getResponse()->getContent();
|
|
|
|
if (!empty($response['data'])) {
|
|
$response['data'][0]['ad_id'] = $row['ad_id'];
|
|
$result = array_merge($result, $response['data']);
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
// 개별 광고 조회 업데이트
|
|
|
|
public function updateAds($data = null)
|
|
{
|
|
try {
|
|
$params = [
|
|
'fields' => [
|
|
AdFields::ID,
|
|
AdFields::NAME,
|
|
AdFields::ADSET_ID,
|
|
AdFields::EFFECTIVE_STATUS,
|
|
AdFields::STATUS,
|
|
//AdFields::RECOMMENDATIONS,
|
|
AdFields::UPDATED_TIME,
|
|
AdFields::CREATED_TIME,
|
|
AdFields::TRACKING_SPECS,
|
|
AdFields::CONVERSION_SPECS
|
|
]
|
|
];
|
|
if ($data == null) {
|
|
$ad_ids = $this->db->getAds();
|
|
$data = $ad_ids->getResultArray();
|
|
}
|
|
$result = [];
|
|
$_ids = [];
|
|
$ids = [];
|
|
foreach ($data as $row) $_ids[] = $row['ad_id'];
|
|
if (count($_ids)) {
|
|
$ids = array_unique($_ids);
|
|
$total = count($ids);
|
|
$step = 1;
|
|
if(is_cli()){
|
|
CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 광고 데이터 수신을 시작합니다.", "light_red");
|
|
}
|
|
foreach ($ids as $ad_id) {
|
|
$this->setAdId($ad_id);
|
|
$ads = $this->ad->getSelf([], $params);
|
|
$response = $ads->getData();
|
|
if(is_cli()){
|
|
CLI::showProgress($step++, $total);
|
|
}
|
|
$result[] = [
|
|
'tracking_specs' => $response['tracking_specs'] ?? [],
|
|
'conversion_specs' => $response['conversion_specs'] ?? [],
|
|
'created_time' => $response['created_time'] ?? '',
|
|
'updated_time' => $response['updated_time'] ?? '',
|
|
'name' => $response['name'] ?? '',
|
|
'id' => $response['id'] ?? '',
|
|
'adset_id' => $response['adset_id'] ?? '',
|
|
'campaign_id' => $response['campaign_id'] ?? '',
|
|
'effective_status' => $response['effective_status'] ?? '',
|
|
'status' => $response['status'] ?? '',
|
|
'fb_pixel' => $response['fb_pixel'] ?? '',
|
|
];
|
|
}
|
|
$this->db->updateAds($result);
|
|
}
|
|
|
|
return $result;
|
|
} catch (Exception $ex) {
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고 정보] 수신 오류 : " . $ex->getMessage(),
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
}
|
|
|
|
// 개별 광고세트 조회 업데이트
|
|
public function updateAdsets($data = null)
|
|
{
|
|
try {
|
|
$params = [
|
|
'fields' => [
|
|
AdSetFields::ID,
|
|
AdSetFields::NAME,
|
|
AdSetFields::CAMPAIGN_ID,
|
|
AdSetFields::EFFECTIVE_STATUS,
|
|
AdSetFields::STATUS,
|
|
AdSetFields::LEARNING_STAGE_INFO,
|
|
//AdSetFields::RECOMMENDATIONS,
|
|
AdSetFields::START_TIME,
|
|
AdSetFields::UPDATED_TIME,
|
|
AdSetFields::CREATED_TIME,
|
|
AdSetFields::DAILY_BUDGET,
|
|
AdSetFields::LIFETIME_BUDGET,
|
|
AdSetFields::BUDGET_REMAINING
|
|
]
|
|
];
|
|
if ($data == null) {
|
|
$adset_ids = $this->db->getAdSetsWithAccount();
|
|
foreach ($adset_ids->getResultArray() as $row) {
|
|
$data[] = $row;
|
|
}
|
|
}
|
|
$result = [];
|
|
$_ids = [];
|
|
$ids = [];
|
|
foreach ($data as $row) $_ids[] = $row['adset_id'];
|
|
if (count($_ids)) {
|
|
$ids = array_unique($_ids);
|
|
$total = count($ids);
|
|
$step = 1;
|
|
if(is_cli()){
|
|
CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 광고그룹 데이터 수신을 시작합니다.", "light_red");
|
|
}
|
|
foreach ($ids as $adset_id) {
|
|
$this->setAdsetId($adset_id);
|
|
$adset = $this->adset->getSelf([], $params);
|
|
$response = $adset->getData();
|
|
// echo '<pre>'.print_r($response,1).'</pre>'; exit;
|
|
if(is_cli()){
|
|
CLI::showProgress($step++, $total);
|
|
}
|
|
$result[] = [
|
|
'budget_remaining' => $response['budget_remaining'] ?? '',
|
|
'start_time' => $response['start_time'] ?? '',
|
|
'created_time' => $response['created_time'] ?? '',
|
|
'updated_time' => $response['updated_time'] ?? '',
|
|
'name' => $response['name'] ?? '',
|
|
'lifetime_budget' => $response['lifetime_budget'] ?? '',
|
|
'daily_budget' => $response['daily_budget'] ?? '',
|
|
'learning_stage_info' => $response['learning_stage_info'] ?? [],
|
|
'id' => $response['id'] ?? '',
|
|
'campaign_id' => $response['campaign_id'] ?? '',
|
|
'effective_status' => $response['effective_status'] ?? '',
|
|
'status' => $response['status'] ?? '',
|
|
];
|
|
}
|
|
$this->db->updateAdsets($result);
|
|
}
|
|
return $result;
|
|
} catch (Exception $ex) {
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고그룹 정보] 수신 오류 : " . $ex->getMessage(),
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
}
|
|
|
|
// 개별 캠페인 조회 업데이트
|
|
public function updateCampaigns($data = null)
|
|
{
|
|
try {
|
|
$params = [
|
|
'fields' => [
|
|
CampaignFields::ID,
|
|
CampaignFields::NAME,
|
|
CampaignFields::ACCOUNT_ID,
|
|
CampaignFields::DAILY_BUDGET,
|
|
CampaignFields::BUDGET_REMAINING,
|
|
CampaignFields::BUDGET_REBALANCE_FLAG,
|
|
CampaignFields::CAN_USE_SPEND_CAP,
|
|
CampaignFields::SPEND_CAP,
|
|
CampaignFields::OBJECTIVE,
|
|
CampaignFields::EFFECTIVE_STATUS,
|
|
CampaignFields::LIFETIME_BUDGET,
|
|
//CampaignFields::RECOMMENDATIONS,
|
|
CampaignFields::STATUS,
|
|
CampaignFields::START_TIME,
|
|
CampaignFields::CREATED_TIME,
|
|
CampaignFields::UPDATED_TIME
|
|
]
|
|
];
|
|
if ($data == null) {
|
|
$campaign_ids = $this->db->getCampaignsWithAccount();
|
|
foreach ($campaign_ids->getResultArray() as $row) {
|
|
$data[] = $row;
|
|
}
|
|
}
|
|
$result = [];
|
|
$_ids = [];
|
|
$ids = [];
|
|
foreach ($data as $row) $_ids[] = $row['campaign_id'];
|
|
if (count($_ids)) {
|
|
$ids = array_unique($_ids);
|
|
$total = count($ids);
|
|
$step = 1;
|
|
if(is_cli()){
|
|
CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 캠페인 데이터 수신을 시작합니다.", "light_red");
|
|
}
|
|
foreach ($ids as $campaign_id) {
|
|
$this->setCampaignId($campaign_id);
|
|
$campaign = $this->campaign->getSelf([], $params);
|
|
$response = $campaign->getData();
|
|
if(is_cli()){
|
|
CLI::showProgress($step++, $total);
|
|
}
|
|
$result[] = [
|
|
'budget_remaining' => $response['budget_remaining'] ?? '',
|
|
'start_time' => $response['start_time'] ?? '',
|
|
'created_time' => $response['created_time'] ?? '',
|
|
'updated_time' => $response['updated_time'] ?? '',
|
|
'name' => $response['name'] ?? '',
|
|
'can_use_spend_cap' => $response['can_use_spend_cap'] ?? '',
|
|
'budget_rebalance_flag' => $response['budget_rebalance_flag'] ?? '',
|
|
'spend_cap' => $response['spend_cap'] ?? '',
|
|
'lifetime_budget' => $response['lifetime_budget'] ?? '',
|
|
'daily_budget' => $response['daily_budget'] ?? '',
|
|
'id' => $response['id'] ?? '',
|
|
'account_id' => $response['account_id'] ?? '',
|
|
'effective_status' => $response['effective_status'] ?? '',
|
|
'status' => $response['status'] ?? '',
|
|
'objective' => $response['objective'] ?? '',
|
|
];
|
|
}
|
|
|
|
$this->db->updateCampaigns($result);
|
|
}
|
|
|
|
return $result;
|
|
} catch (Exception $ex) {
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][캠페인 정보] 수신 오류 : " . $ex->getMessage(),
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
}
|
|
|
|
// 광고 조회
|
|
public function getAds()
|
|
{
|
|
try {
|
|
$params = [
|
|
// 'time_range' => ['since'=>date('Y-m-d', strtotime('-2 year')), 'until'=>date('Y-m-d')],
|
|
// 'date_preset' => 'today',
|
|
AdFields::EFFECTIVE_STATUS => [
|
|
'ACTIVE',
|
|
// 'ADSET_PAUSED',
|
|
// 'ARCHIVED',
|
|
// 'CAMPAIGN_PAUSED',
|
|
// 'DELETED',
|
|
'DISAPPROVED',
|
|
// 'IN_PROCESS',
|
|
'PAUSED',
|
|
'PENDING_BILLING_INFO',
|
|
'PENDING_REVIEW',
|
|
'PREAPPROVED',
|
|
'WITH_ISSUES'
|
|
],
|
|
/*
|
|
AdFields::STATUS => array(
|
|
'ACTIVE',
|
|
'PAUSED'
|
|
),*/
|
|
'fields' => [
|
|
AdFields::ID,
|
|
AdFields::NAME,
|
|
AdFields::ADSET_ID,
|
|
AdFields::EFFECTIVE_STATUS,
|
|
AdFields::STATUS,
|
|
AdFields::RECOMMENDATIONS,
|
|
AdFields::UPDATED_TIME,
|
|
AdFields::CREATED_TIME,
|
|
AdFields::TRACKING_SPECS,
|
|
AdFields::CONVERSION_SPECS
|
|
]
|
|
];
|
|
|
|
$ad_accounts = $this->db->getAdAccounts(); // 각 광고 계정별
|
|
$total = $ad_accounts->getNumRows();
|
|
$step = 1;
|
|
$result = [];
|
|
CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 계정에 대한 광고 데이터 수신을 시작합니다.", "light_red");
|
|
foreach ($ad_accounts->getResultArray() as $row) {
|
|
// $row['ad_account_id'] = 796319794698742;
|
|
$this->setAdAccount($row['ad_account_id']);
|
|
$ads = $this->account->getAds([], $params);
|
|
$response = $ads->getResponse()->getContent();
|
|
CLI::showProgress($step++, $total);
|
|
$result = array_merge($result, $response['data']);
|
|
if (isset($response['paging'])) {
|
|
$url = isset($response['paging']['next']) ? $response['paging']['next'] : false;
|
|
while ($url) {
|
|
$data = $this->getFBRequest_CURL($url);
|
|
|
|
if (isset($data['data'])) {
|
|
$result = array_merge($result, $data['data']);
|
|
}
|
|
|
|
$url = isset($data['paging']['next']) ? $data['paging']['next'] : false;
|
|
}
|
|
}
|
|
// echo '<pre>'.print_r($result,1).'</pre>'; exit;
|
|
}
|
|
$this->db->updateAds($result);
|
|
return $result;
|
|
} catch (Exception $ex) {
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고 정보] 수신 오류 : " . $ex->getMessage(),
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
}
|
|
|
|
// 페이징 전용 함수
|
|
private function getFBRequest_CURL($url)
|
|
{
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 600);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
$result = curl_exec($ch);
|
|
curl_close($ch);
|
|
|
|
$data = json_decode($result, true);
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function adLeadByAd($ad_id, $from = "-1 day", $to = null) {
|
|
$result = [];
|
|
$params = [];
|
|
// 시작 날짜
|
|
$from_dt = new DateTime($from);
|
|
$from_dt->format('Y-m-d 00:00:00');
|
|
$from_date = $from_dt->getTimestamp();
|
|
|
|
$params['filtering'] = [
|
|
[
|
|
'field' => 'time_created',
|
|
'operator' => 'GREATER_THAN',
|
|
'value' => $from_date
|
|
],
|
|
];
|
|
|
|
// 끝 날짜
|
|
if ($from !== "-1 day" && $to !== null) {
|
|
$to_dt = new DateTime($to." 23:59:59");
|
|
$to_dt->format('Y-m-d H:i:s');
|
|
$to_date = $to_dt->getTimestamp();
|
|
|
|
$params['filtering'][1] = [
|
|
'field' => 'time_created',
|
|
'operator' => 'LESS_THAN',
|
|
'value' => $to_date
|
|
];
|
|
}
|
|
|
|
$fields = [
|
|
LeadFields::ID,
|
|
LeadFields::FORM_ID,
|
|
LeadFields::AD_ID,
|
|
LeadFields::AD_NAME,
|
|
LeadFields::ADSET_ID,
|
|
LeadFields::ADSET_NAME,
|
|
LeadFields::CAMPAIGN_ID,
|
|
LeadFields::CAMPAIGN_NAME,
|
|
LeadFields::IS_ORGANIC,
|
|
LeadFields::FIELD_DATA,
|
|
LeadFields::CREATED_TIME,
|
|
LeadFields::CUSTOM_DISCLAIMER_RESPONSES
|
|
];
|
|
$this->setAdId($ad_id);
|
|
$leads = $this->ad->getLeads($fields, $params);
|
|
$response = $leads->getResponse()->getContent();
|
|
$lead_data = [];
|
|
if (!empty($response['data'])) {
|
|
$lead_data = array_merge($lead_data, $response['data']);
|
|
$result = array_merge($result, $response['data']);
|
|
}
|
|
if (isset($response['paging'])) {
|
|
$url = isset($response['paging']['next']) ? $response['paging']['next'] : false;
|
|
while ($url) {
|
|
$data = $this->getFBRequest_CURL($url);
|
|
if (isset($data['data'])) {
|
|
$lead_data = array_merge($lead_data, $response['data']);
|
|
$result = array_merge($result, $data['data']);
|
|
}
|
|
$url = isset($data['paging']['next']) ? $data['paging']['next'] : false;
|
|
}
|
|
}
|
|
if(count($lead_data))
|
|
$this->db->insertAdLeads($lead_data);
|
|
return $lead_data;
|
|
}
|
|
|
|
// 각 AdID별 폼 목록
|
|
public function getAdLead($from = "-1 day", $to = null)
|
|
{
|
|
try {
|
|
$result = [];
|
|
$params = [];
|
|
|
|
// 시작 날짜
|
|
$from_dt = new DateTime($from);
|
|
$from_dt->format('Y-m-d 00:00:00');
|
|
$from_date = $from_dt->getTimestamp();
|
|
|
|
$params['filtering'] = [
|
|
[
|
|
'field' => 'time_created',
|
|
'operator' => 'GREATER_THAN',
|
|
'value' => $from_date
|
|
],
|
|
];
|
|
|
|
// 끝 날짜
|
|
if ($from !== "-1 day" && $to !== null) {
|
|
$to_dt = new DateTime($to." 23:59:59");
|
|
$to_dt->format('Y-m-d H:i:s');
|
|
$to_date = $to_dt->getTimestamp();
|
|
|
|
$params['filtering'][1] = [
|
|
'field' => 'time_created',
|
|
'operator' => 'LESS_THAN',
|
|
'value' => $to_date
|
|
];
|
|
}
|
|
|
|
$fields = [
|
|
LeadFields::ID,
|
|
LeadFields::FORM_ID,
|
|
LeadFields::AD_ID,
|
|
LeadFields::AD_NAME,
|
|
LeadFields::ADSET_ID,
|
|
LeadFields::ADSET_NAME,
|
|
LeadFields::CAMPAIGN_ID,
|
|
LeadFields::CAMPAIGN_NAME,
|
|
LeadFields::IS_ORGANIC,
|
|
LeadFields::FIELD_DATA,
|
|
LeadFields::CREATED_TIME,
|
|
LeadFields::CUSTOM_DISCLAIMER_RESPONSES
|
|
];
|
|
|
|
$ad_ids = $this->db->getLeadgenAds(); //from DB
|
|
$total = $ad_ids->getNumRows();
|
|
$step = 1;
|
|
CLI::write("[".date("Y-m-d H:i:s")."]"."{$total}개의 광고에서 {$from} ~ {$to} 기간의 잠재고객 데이터를 수신합니다.", "light_red");
|
|
foreach ($ad_ids->getResultArray() as $row) { //while $row['page_id']
|
|
CLI::showProgress($step++, $total);
|
|
if ($row['leadgen_id'] == null || $row['leadgen_id'] == '' || $row['status'] != 'ACTIVE') {// || strtotime($row['update_date']) <= strtotime('-1 month')) { //소재가 1개월 이상 업데이트 되지 않았으면 잠재고객을 받지 않음
|
|
continue;
|
|
}
|
|
// echo '<pre>'.print_r($row,1).'</pre>';
|
|
$this->setAdId($row['ad_id']);
|
|
$leads = $this->ad->getLeads($fields, $params);
|
|
$response = $leads->getResponse()->getContent();
|
|
$lead_data = [];
|
|
if (!empty($response['data'])) {
|
|
$lead_data = array_merge($lead_data, $response['data']);
|
|
$result = array_merge($result, $response['data']);
|
|
}
|
|
if (isset($response['paging'])) {
|
|
$url = isset($response['paging']['next']) ? $response['paging']['next'] : false;
|
|
while ($url) {
|
|
$data = $this->getFBRequest_CURL($url);
|
|
if (isset($data['data'])) {
|
|
$lead_data = array_merge($lead_data, $data['data']);
|
|
$result = array_merge($result, $data['data']);
|
|
}
|
|
$url = isset($data['paging']['next']) ? $data['paging']['next'] : false;
|
|
}
|
|
}
|
|
if(count($lead_data)) {
|
|
$this->db->insertAdLeads($lead_data);
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
} catch (Exception $ex) {
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][잠재고객] 수신 오류 : " . $ex->getMessage(),
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
}
|
|
}
|
|
|
|
|
|
public function updateAdAccounts()
|
|
{
|
|
|
|
$result = [];
|
|
foreach($this->business_id_list as $bs_id) {
|
|
self::setBusinessId($bs_id);
|
|
$accounts = self::getFBAccounts();
|
|
$this->db->updateAdAccounts($accounts);
|
|
$result = array_merge($result, $accounts);
|
|
}
|
|
$msgs = [
|
|
'channel' => $this->slackChannel,
|
|
'text' => "[".date("Y-m-d H:i:s")."][" . getenv('MY_SERVER_NAME') . "][페이스북][광고계정] 수신 완료",
|
|
];
|
|
$this->slack->sendMessage($msgs);
|
|
return $result;
|
|
}
|
|
|
|
public function getCampaignStatusBudget($campaign_id)
|
|
{
|
|
$params = [
|
|
'fields' => [
|
|
CampaignFields::ID,
|
|
CampaignFields::DAILY_BUDGET,
|
|
CampaignFields::STATUS,
|
|
]
|
|
];
|
|
|
|
$this->setCampaignId($campaign_id);
|
|
$campaign = $this->campaign->getSelf([], $params);
|
|
$response = $campaign->getData();
|
|
|
|
$result = [
|
|
'id' => $response['id'],
|
|
'budget' => $response['daily_budget'],
|
|
'status' => $response['status']
|
|
];
|
|
return $result;
|
|
}
|
|
|
|
//광고 상태 업데이트
|
|
public function setCampaignStatus($id, $status)
|
|
{
|
|
$result = [];
|
|
$statusValue = $status == 'ACTIVE' ? Campaign::STATUS_ACTIVE : Campaign::STATUS_PAUSED;
|
|
|
|
$this->setCampaignId($id);
|
|
$campaign = $this->campaign->updateSelf([], [
|
|
Campaign::STATUS_PARAM_NAME => $statusValue,
|
|
]);
|
|
|
|
$campaign = $campaign->getData();
|
|
if ($campaign['success'] == 1) {
|
|
$this->db->setCampaignStatus($id, $status);
|
|
$result = ['response' => true];
|
|
return $result;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function getAdsetStatusBudget($adset_id)
|
|
{
|
|
$params = [
|
|
'fields' => [
|
|
AdSetFields::ID,
|
|
AdSetFields::STATUS,
|
|
AdSetFields::DAILY_BUDGET,
|
|
AdSetFields::LIFETIME_BUDGET,
|
|
]
|
|
];
|
|
|
|
$row = $this->db->getAdSet($adset_id);
|
|
switch ($row['budget_type']) {
|
|
case 'lifetime':
|
|
$params[] = AdSetFields::LIFETIME_BUDGET;
|
|
break;
|
|
case 'daily':
|
|
$params[] = AdSetFields::DAILY_BUDGET;
|
|
break;
|
|
default:
|
|
return null;
|
|
}
|
|
|
|
$this->setAdsetId($adset_id);
|
|
$adset = $this->adset->getSelf([], $params);
|
|
$response = $adset->getData();
|
|
if ($response['success'] == 1) {
|
|
$result = [
|
|
'id' => $response['id'],
|
|
'status' => $response['status']
|
|
];
|
|
switch ($row['budget_type']) {
|
|
case 'lifetime':
|
|
$result['budget'] = $response['lifetime_budget'];
|
|
break;
|
|
case 'daily':
|
|
$result['budget'] = $response['daily_budget'];
|
|
break;
|
|
default:
|
|
return null;
|
|
}
|
|
return $result;
|
|
}else{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function setAdsetStatus($id, $status)
|
|
{
|
|
$result = [];
|
|
$statusValue = $status == 'ACTIVE' ? AdSet::STATUS_ACTIVE : AdSet::STATUS_PAUSED;
|
|
|
|
$this->setAdsetId($id);
|
|
$adset = $this->adset->updateSelf([], [
|
|
AdSet::STATUS_PARAM_NAME => $statusValue,
|
|
]);
|
|
$adset = $adset->getData();
|
|
if ($adset['success'] == 1) {
|
|
$this->db->setAdsetStatus($id, $status);
|
|
$result = ['response' => true];
|
|
return $result;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function getAdStatusBudget($ad_id)
|
|
{
|
|
$params = [
|
|
'fields' => [
|
|
AdFields::ID,
|
|
AdFields::STATUS,
|
|
]
|
|
];
|
|
|
|
$this->setAdId($ad_id);
|
|
$ads = $this->ad->getSelf([], $params);
|
|
$response = $ads->getData();
|
|
|
|
$result = [
|
|
'id' => $response['id'],
|
|
'status' => $response['status']
|
|
];
|
|
return $result;
|
|
}
|
|
|
|
public function setAdStatus($id, $status)
|
|
{
|
|
$result = [];
|
|
$statusValue = $status == 'ACTIVE' ? Ad::STATUS_ACTIVE : Ad::STATUS_PAUSED;
|
|
|
|
$this->setAdId($id);
|
|
$ad = $this->ad->updateSelf([], [
|
|
Ad::STATUS_PARAM_NAME => $statusValue,
|
|
]);
|
|
$ad = $ad->getData();
|
|
if ($ad['success'] == 1) {
|
|
$this->db->setAdStatus($id, $status);
|
|
$result = ['response' => true];
|
|
return $result;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function updateCampaignBudget($data)
|
|
{
|
|
//한개씩 캠페인 일일예산 수정
|
|
$campaign_id = $data['id'] ?? null;
|
|
$budget = $data['budget'] ?? null;
|
|
|
|
if (!$campaign_id || $budget === null) {
|
|
return null;
|
|
}
|
|
|
|
$row = $this->db->getCampaign($campaign_id);
|
|
// 기본 정보 설정
|
|
$campaignfields = [CampaignFields::DAILY_BUDGET => intval($budget)];
|
|
|
|
$campaign = new Campaign($campaign_id);
|
|
|
|
// $campaign->setData($campaignfields);
|
|
$campaign = $campaign->updateSelf([], $campaignfields);
|
|
$campaign = $campaign->getData();
|
|
|
|
if ($campaign['success'] == 1) {
|
|
$this->db->updateCampaignBudget($campaign_id, $budget);
|
|
return $campaign_id;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function updateAdSetBudget($data)
|
|
{
|
|
//한개씩 일일예산 수정
|
|
$adset_id = $data['id'] ?? null;
|
|
$budget = $data['budget'] ?? null;
|
|
if (!$adset_id || !$budget || $budget < 1000) {
|
|
return null;
|
|
}
|
|
$row = $this->db->getAdSet($adset_id);
|
|
$field = '';
|
|
switch ($row['budget_type']) {
|
|
case 'lifetime':
|
|
$field = AdSetFields::LIFETIME_BUDGET;
|
|
break;
|
|
case 'daily':
|
|
$field = AdSetFields::DAILY_BUDGET;
|
|
break;
|
|
}
|
|
// 기본 정보 설정
|
|
$adsetfields = [$field => $budget];
|
|
|
|
$adset = new AdSet($adset_id);
|
|
// $adset->setData($adsetfields);
|
|
$adset = $adset->updateSelf([], $adsetfields);
|
|
$adset = $adset->getData();
|
|
|
|
if ($adset['success'] == 1) {
|
|
$this->db->updateAdSetBudget($adset_id, $budget);
|
|
return $adset_id;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function updateName($data)
|
|
{
|
|
$id = trim($data['id'] ?? '');
|
|
$type = trim($data['type'] ?? '');
|
|
|
|
if (!$id || !$type) {
|
|
return null;
|
|
}
|
|
$result = '';
|
|
switch ($type) {
|
|
case 'campaigns':
|
|
$result = $this->updateCampaignName($data);
|
|
break;
|
|
case 'adsets':
|
|
$result = $this->updateAdsetName($data);
|
|
break;
|
|
case 'ads':
|
|
$result = $this->updateAdName($data);
|
|
break;
|
|
default:
|
|
return null;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
private function updateCampaign(array $fields, array $data)
|
|
{
|
|
if (empty($fields) || empty($data)) {
|
|
return null;
|
|
}
|
|
|
|
if (empty($data['id'])) {
|
|
return null;
|
|
}
|
|
|
|
$campaign = new Campaign($data['id']);
|
|
// $campaign->setData($fields);
|
|
$campaign = $campaign->updateSelf([], $data);
|
|
$campaign = $campaign->getData();
|
|
if ($campaign['success'] == 1) {
|
|
return $data;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function updateAdset(array $fields, array $data)
|
|
{
|
|
if (empty($fields) || empty($data)) {
|
|
return null;
|
|
}
|
|
|
|
if (empty($data['id'])) {
|
|
return null;
|
|
}
|
|
|
|
$adset = new AdSet($data['id']);
|
|
// $adset->setData($fields);
|
|
$adset = $adset->updateSelf([], $data);
|
|
$adset = $adset->getData();
|
|
if ($adset['success'] == 1) {
|
|
return $data;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function updateAd(array $fields, array $data)
|
|
{
|
|
if (empty($fields) || empty($data)) {
|
|
return null;
|
|
}
|
|
|
|
if (empty($data['id'])) {
|
|
return null;
|
|
}
|
|
|
|
$ad = new Ad($data['id']);
|
|
// $ad->setData($fields);
|
|
$ad = $ad->updateSelf([], $data);
|
|
$ad = $ad->getData();
|
|
if ($ad['success'] == 1) {
|
|
return $data;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function updateCampaignName(array $data)
|
|
{
|
|
if(empty($data['name'])){
|
|
return null;
|
|
}
|
|
|
|
$fields = [CampaignFields::NAME => $data['name']];
|
|
$apiResult = $this->updateCampaign($fields, $data);
|
|
if ($apiResult) {
|
|
$this->db->updateCampaignName($data);
|
|
return $apiResult;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function updateAdsetName(array $data)
|
|
{
|
|
if(empty($data['name'])){
|
|
return null;
|
|
}
|
|
|
|
$fields = [AdSetFields::NAME => $data['name']];
|
|
$apiResult = $this->updateAdset($fields, $data);
|
|
if ($apiResult) {
|
|
$this->db->updateAdsetName($data);
|
|
return $apiResult;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function updateAdName(array $data)
|
|
{
|
|
if(empty($data['name'])){
|
|
return null;
|
|
}
|
|
|
|
$fields = [AdFields::NAME => $data['name']];
|
|
$apiResult = $this->updateAd($fields, $data);
|
|
if ($apiResult) {
|
|
$this->db->updateAdName($data);
|
|
return $apiResult;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function setManualUpdate($campaignIds)
|
|
{
|
|
if(!$campaignIds){return false;}
|
|
|
|
$campaignParam = [
|
|
CampaignFields::ID,
|
|
CampaignFields::NAME,
|
|
CampaignFields::ACCOUNT_ID,
|
|
CampaignFields::DAILY_BUDGET,
|
|
CampaignFields::BUDGET_REMAINING,
|
|
CampaignFields::BUDGET_REBALANCE_FLAG,
|
|
CampaignFields::CAN_USE_SPEND_CAP,
|
|
CampaignFields::SPEND_CAP,
|
|
CampaignFields::OBJECTIVE,
|
|
CampaignFields::EFFECTIVE_STATUS,
|
|
//CampaignFields::RECOMMENDATIONS,
|
|
CampaignFields::STATUS,
|
|
CampaignFields::START_TIME,
|
|
CampaignFields::CREATED_TIME,
|
|
CampaignFields::UPDATED_TIME
|
|
];
|
|
|
|
$adsetParam = [
|
|
AdSetFields::ID,
|
|
AdSetFields::NAME,
|
|
AdSetFields::CAMPAIGN_ID,
|
|
AdSetFields::EFFECTIVE_STATUS,
|
|
AdSetFields::STATUS,
|
|
AdSetFields::LEARNING_STAGE_INFO,
|
|
//AdSetFields::RECOMMENDATIONS,
|
|
AdSetFields::START_TIME,
|
|
AdSetFields::UPDATED_TIME,
|
|
AdSetFields::CREATED_TIME,
|
|
AdSetFields::DAILY_BUDGET,
|
|
AdSetFields::LIFETIME_BUDGET,
|
|
AdSetFields::BUDGET_REMAINING
|
|
];
|
|
|
|
$adParam = [
|
|
AdFields::ID,
|
|
AdFields::NAME,
|
|
AdFields::ADSET_ID,
|
|
AdFields::EFFECTIVE_STATUS,
|
|
AdFields::STATUS,
|
|
//AdFields::RECOMMENDATIONS,
|
|
AdFields::UPDATED_TIME,
|
|
AdFields::CREATED_TIME,
|
|
AdFields::TRACKING_SPECS,
|
|
AdFields::CONVERSION_SPECS
|
|
];
|
|
|
|
$adCreativeParams = [
|
|
'thumbnail_width' => 250,
|
|
'thumbnail_height' => 250,
|
|
];
|
|
|
|
$adCreativeFields = [
|
|
AdCreativeFields::ID,
|
|
AdCreativeFields::BODY,
|
|
AdCreativeFields::OBJECT_TYPE,
|
|
AdCreativeFields::OBJECT_URL,
|
|
AdCreativeFields::THUMBNAIL_URL,
|
|
AdCreativeFields::IMAGE_FILE,
|
|
AdCreativeFields::IMAGE_URL,
|
|
AdCreativeFields::CALL_TO_ACTION_TYPE,
|
|
AdCreativeFields::OBJECT_STORY_SPEC
|
|
];
|
|
|
|
$campaignResult = [];
|
|
foreach ($campaignIds as $campaignId) {
|
|
$this->setCampaignId($campaignId);
|
|
$campaign = $this->campaign->read($campaignParam);
|
|
$campaignResponse = $campaign->getData();
|
|
$campaignResult[] = [
|
|
'budget_remaining' => $campaignResponse['budget_remaining'] ?? '',
|
|
'start_time' => $campaignResponse['start_time'] ?? '',
|
|
'created_time' => $campaignResponse['created_time'] ?? '',
|
|
'updated_time' => $campaignResponse['updated_time'] ?? '',
|
|
'name' => $campaignResponse['name'] ?? '',
|
|
'can_use_spend_cap' => $campaignResponse['can_use_spend_cap'] ?? '',
|
|
'budget_rebalance_flag' => $campaignResponse['budget_rebalance_flag'] ?? '',
|
|
'spend_cap' => $campaignResponse['spend_cap'] ?? '',
|
|
'lifetime_budget' => $campaignResponse['lifetime_budget'] ?? '',
|
|
'daily_budget' => $campaignResponse['daily_budget'] ?? '',
|
|
'id' => $campaignResponse['id'] ?? '',
|
|
'account_id' => $campaignResponse['account_id'] ?? '',
|
|
'effective_status' => $campaignResponse['effective_status'] ?? '',
|
|
'status' => $campaignResponse['status'] ?? '',
|
|
'objective' => $campaignResponse['objective'] ?? '',
|
|
];
|
|
|
|
$adsetResult = [];
|
|
$adsets = $this->campaign->getAdSets($adsetParam);
|
|
foreach ($adsets as $adset) {
|
|
$adsetResponse = $adset->getData();
|
|
$adsetResult[] = [
|
|
'budget_remaining' => $adsetResponse['budget_remaining'] ?? '',
|
|
'start_time' => $adsetResponse['start_time'] ?? '',
|
|
'created_time' => $adsetResponse['created_time'] ?? '',
|
|
'updated_time' => $adsetResponse['updated_time'] ?? '',
|
|
'name' => $adsetResponse['name'] ?? '',
|
|
'lifetime_budget' => $adsetResponse['lifetime_budget'] ?? '',
|
|
'daily_budget' => $adsetResponse['daily_budget'] ?? '',
|
|
'learning_stage_info' => $adsetResponse['learning_stage_info'] ?? [],
|
|
'id' => $adsetResponse['id'] ?? '',
|
|
'campaign_id' => $adsetResponse['campaign_id'] ?? '',
|
|
'effective_status' => $adsetResponse['effective_status'] ?? '',
|
|
'status' => $adsetResponse['status'] ?? '',
|
|
];
|
|
|
|
$adResult = [];
|
|
$ads = $adset->getAds($adParam);
|
|
foreach ($ads as $ad) {
|
|
$adResponse = $ad->getData();
|
|
$adResult[] = [
|
|
'tracking_specs' => $adResponse['tracking_specs'] ?? [],
|
|
'conversion_specs' => $adResponse['conversion_specs'] ?? [],
|
|
'created_time' => $adResponse['created_time'] ?? '',
|
|
'updated_time' => $adResponse['updated_time'] ?? '',
|
|
'name' => $adResponse['name'] ?? '',
|
|
'id' => $adResponse['id'] ?? '',
|
|
'adset_id' => $adResponse['adset_id'] ?? '',
|
|
'campaign_id' => $adResponse['campaign_id'] ?? '',
|
|
'effective_status' => $adResponse['effective_status'] ?? '',
|
|
'status' => $adResponse['status'] ?? '',
|
|
'fb_pixel' => $adResponse['fb_pixel'] ?? '',
|
|
];
|
|
|
|
$adCreatives = $ad->getAdCreatives($adCreativeFields, $adCreativeParams);
|
|
foreach ($adCreatives as $adCreative) {
|
|
$acResponse = $adCreative->getData();
|
|
$acResponse['ad_id'] = $adResponse['id'];
|
|
$acResult[] = $acResponse;
|
|
}
|
|
$result = $this->updateAdcreatives(null, $acResult);
|
|
if(!$result){
|
|
return false;
|
|
}
|
|
}
|
|
$result = $this->db->updateAds($adResult);
|
|
if(!$result){
|
|
return false;
|
|
}
|
|
}
|
|
$result = $this->db->updateAdsets($adsetResult);
|
|
if(!$result){
|
|
return false;
|
|
}
|
|
}
|
|
$result = $this->db->updateCampaigns($campaignResult);
|
|
if(!$result){
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function landingGroup($title)
|
|
{
|
|
if (empty($title)) return null;
|
|
preg_match_all('/.+\#([0-9]+)?(\_([0-9]+))?([\s]+)?(\*([0-9]+)?)?([\s]+)?(\&([a-z]+))?([\s]+)?(\^([0-9]+))?/i', $title, $matches);
|
|
if(!isset($matches[9][0])) $matches[9][0] = "";
|
|
switch ($matches[9][0]) {
|
|
case 'fer': $media = '이벤트 랜딩'; break;
|
|
case 'fercpm': $media = '이벤트 랜딩_cpm'; break;
|
|
case 'ler': $media = '이벤트 잠재고객'; break;
|
|
case 'lercpm': $media = '이벤트 잠재고객_cpm'; break;
|
|
case 'cpm': $media = 'cpm'; break;
|
|
default: $media = '';break;
|
|
}
|
|
if ($media) {
|
|
$period_ad = isset($matches[12][0]) && $matches[12][0] ? $matches[12][0] : 0;
|
|
$result = [
|
|
'name' => $matches[0][0] ?? ''
|
|
,'media' => $media
|
|
,'media_code' => $matches[9][0]??''
|
|
,'event_seq' => $matches[1][0] ?? ''
|
|
,'site' => $matches[3][0] ?? ''
|
|
,'db_price' => $matches[6][0] ?? 0
|
|
,'period_ad' => $period_ad
|
|
];
|
|
return $result;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function getAdsUseLanding($date = null)
|
|
{
|
|
//유효DB 개수 업데이트
|
|
if ($date == null) {
|
|
$date = date('Y-m-d');
|
|
}
|
|
$ads = $this->db->getAdLeads($date);
|
|
$step = 1;
|
|
$total = $ads->getNumRows();
|
|
if(!$total) return null;
|
|
$result = [];
|
|
foreach($ads->getResultArray() as $row) {
|
|
$error = [];
|
|
CLI::showProgress($step++, $total);
|
|
if (!empty($row['code'])) {
|
|
$title = trim($row['code']);
|
|
}else{
|
|
$title = $row['ad_name'];
|
|
}
|
|
$landing = $this->landingGroup($title); //소재와 이벤트 매칭
|
|
$data = [];
|
|
$data = [
|
|
'date' => $date
|
|
,'ad_id' => $row['ad_id']
|
|
];
|
|
if(!is_null($landing)){
|
|
$data = array_merge($data, $landing);
|
|
if (!preg_match('/cpm/', $landing['media'])) {
|
|
if (!$landing['event_seq']) $error[] = $row['ad_name'] . '(' . $row['ad_id'] . '): 이벤트번호 미입력' . PHP_EOL;
|
|
if (!$landing['db_price']) $error[] = $row['ad_name'] . '(' . $row['ad_id'] . '): DB단가 미입력' . PHP_EOL;
|
|
}
|
|
}else if(preg_match('/&[a-z]+/', $row['ad_name'])){
|
|
$error[] = $row['ad_name'] . '(' . $row['ad_id'] . '): 인식 오류' . PHP_EOL;
|
|
}
|
|
|
|
if(!empty($error)){
|
|
foreach($error as $err) CLI::write("{$err}", "light_purple");
|
|
}
|
|
|
|
if(empty($landing)) continue;
|
|
|
|
$dp = $this->db->getDbPrice($data);
|
|
$leads = $this->db->getLeads($data);
|
|
$cpm = false;
|
|
if(is_null($leads) && $data['media'] === 'cpm') $cpm = true;
|
|
$db_price = $data['db_price'];
|
|
if(isset($dp['db_price']) && $data['date'] != date('Y-m-d'))
|
|
$db_price = $data['db_price'] = $dp['db_price'];
|
|
/*
|
|
*수익, 매출액 계산
|
|
!xxxcpm - 유효db n / 수익,매출0
|
|
!cpm - 유효db 0 / 수익,매출0
|
|
!period - ^25 = *0.25
|
|
*/
|
|
$sp_data = json_decode($row['spend_data'],1);
|
|
if(!$data['event_seq'] && $data['media']) {
|
|
foreach($sp_data as $hour => $spend) {
|
|
$margin = 0;
|
|
if($data['period_ad']) $margin = $spend * ('0.' . $data['period_ad']);
|
|
$data['data'][] = ['hour' => $hour,'spend' => $spend,'count' => "",'sales' => "",'margin' => $margin];
|
|
}
|
|
}
|
|
$initZero = false;
|
|
if(preg_match('/cpm/i', $data['media'])) //cpm (fhrm, fhspcpm, jhrcpm) 계산을 무효화
|
|
$initZero = true;
|
|
$lead = [];
|
|
if(!is_null($leads)) {
|
|
foreach($leads->getResultArray() as $row) {
|
|
// if($data['ad_id'] == 23853888597370162) dd($row);
|
|
$sales = 0;
|
|
$db_count = $row['db_count'] ?? 0;
|
|
if($db_price) $sales = $db_price * $db_count;
|
|
if($initZero) $sales = 0;
|
|
if(preg_match('/cpm/i', $data['media'])) $db_count = 0;
|
|
$lead[$row['hour']] = [
|
|
'sales' => $sales
|
|
,'db_count' => $db_count
|
|
];
|
|
}
|
|
}
|
|
for($i=0; $i<=23; $i++) { //DB수량이 없어도 지출금액이 갱신되어야하기 때문에 0~23시까지 모두 저장
|
|
// if($data['ad_id'] == 23853888597370162) dd($lead);
|
|
$hour = $i;
|
|
$spend = $sp_data[$i]??0;
|
|
$count = $lead[$i]['db_count']??0;
|
|
$sales = $lead[$i]['sales']??0;
|
|
$margin = $sales - $spend;
|
|
if($initZero) $margin = $sales = 0;
|
|
if(preg_match('/cpm/i', $data['media'])) $count = 0;
|
|
if($data['period_ad']) $margin = $spend * ('0.' . $data['period_ad']);
|
|
$data['data'][] = [
|
|
'hour' => $hour
|
|
,'spend' => $spend
|
|
,'count' => $count
|
|
,'sales' => $sales
|
|
,'margin' => $margin
|
|
];
|
|
$result = array_merge($result, $data);
|
|
}
|
|
// d($data);
|
|
// if($data['ad_id'] == 23852707712760746) dd($data);
|
|
if(isset($data['ad_id'])) $this->db->updateInsight($data);
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
public static function exception_handler($e)
|
|
{
|
|
//echo nl2br(print_r($e,1));
|
|
echo ('<xmp style="color:#fff;background-color:#000;">');
|
|
print_r($e);
|
|
echo ('</xmp>');
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
public function getMemo($data)
|
|
{
|
|
if(!empty($data)){
|
|
$response = $this->db->getMemo($data);
|
|
return $response;
|
|
}
|
|
}
|
|
|
|
public function addMemo($data)
|
|
{
|
|
if(!empty($data)){
|
|
return $this->db->addMemo($data);
|
|
}
|
|
}
|
|
|
|
public function updateMemo($data)
|
|
{
|
|
if(!empty($data)){
|
|
return $this->db->updateMemo($data);
|
|
}
|
|
}
|
|
}
|