crontabAdjustData.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. <?php
  2. const ChannelTrackMaps = [
  3. "Organic" => [ "g1b8nag" ],
  4. "游戏内部跟踪链接" => [ "yhm47x1", "sij469x", "ynlt7ad", "l67x2mt", "6jq5m5g", "a7krf04", "v4x1byi", "327ogs3", "vt67uin", "cl7yqth", "fqupiw4", "b8q4iua", "x2ao8dk", "tri542t", "c9h1f36", "nua60j4", "o5rfavc" ],
  5. "社媒KOL" => [ "ys85rvc", "n3l2809", "d2p6i5s", "oscpr9r" ],
  6. "各平台主页渠道" => [ "a9nv7dj", "53ece3e", "1z942q1", "d7wopl7", "j7u6h9x", "to6eamo" ],
  7. "邮件营销" => [ "cj6x62s", "pgdmu1z", "4x6dr4w" ],
  8. "游戏外邀请" => [ "1jn49bp", "y8phovy" ],
  9. "Facebook" => [ "2xgabxp", "k1qjyjr", "cwvjh9o", "oss8d1v" ],
  10. "Google_ads" => [ "ussdj6t", "n6mofty" ],
  11. "苹果商店页搜索广告" => [ "rs64xuy" ],
  12. "Unity" => [ "u69nimr" ],
  13. "Applovin" => [ "kkph0xk" ],
  14. "IronSource" => [ "vjjyyf2" ],
  15. "Chartboost" => [ "14dbbj0" ],
  16. "Mintegral" => [ "r2phf78" ],
  17. "Vungle" => [ "6j6t1sg" ],
  18. "Inplayable" => [ "n4tb7gp" ],
  19. "Linkme" => [ "yw8hp34" ],
  20. "Tecdo" => [ "vbc3665" ],
  21. "Virgrilmedia" => [ "6366s1a" ],
  22. "TikTok" => [ "6xxj7ry" ],
  23. "Prodege" => [ "ji2y5ap" ],
  24. ];
  25. const ViewChannels = [
  26. "Facebook", "Google_ads", "Mintegral", "苹果商店页搜索广告", "TikTok"
  27. ];
  28. if (substr(PHP_SAPI_NAME(), 0, 3) !== 'cli') {
  29. die("The program runs only in CLI mode!");
  30. }
  31. const API_TOKEN = 'Tha-k75HDFTdG9WE_s58';
  32. const APP_TOKEN = 'rv3fkx1a8em8';
  33. const DB_CONN = 'backend';
  34. const API_URL = 'https://dash.adjust.com/control-center/reports-service/report?';
  35. !defined('TIMESTAMP') && define('TIMESTAMP', time());
  36. $sid = $lid = 1;
  37. include_once dirname(__FILE__) . "/crontab.inc.php";
  38. include_once dirname(__FILE__) . "/../com.php";
  39. set_time_limit(0);
  40. $hi = date('Hi', TIMESTAMP);
  41. if (!empty($argv[1]))$hi = $argv[1];
  42. oo::logs()->debug3( "hi:{$hi}, time:". TIMESTAMP, 'adjustDataCrontab');
  43. switch ($hi){
  44. case '0000':// 8点00分 拉取周报
  45. case '0800':// 8点00分 拉取周报
  46. Adjust::adjustReport('week') ;
  47. break;
  48. case '0015':// 8点15分 拉取周报
  49. case '0815':// 8点15分 拉取周报
  50. Adjust::adjustReport('day') ;
  51. break;
  52. case '0030':// 8点30分 拉取月报
  53. case '0830':// 8点30分 拉取月报
  54. Adjust::adjustReport('month') ;
  55. break;
  56. case '0045':// 8点45分 拉取日报明细
  57. Adjust::adjustReportCampaign() ;
  58. break;
  59. case '0845':// 8点45分 拉取日报明细
  60. Adjust::adjustReportCampaign(7) ;
  61. break;
  62. case '0010':// 9点 拉取日报明细
  63. Adjust::adjustReportViews() ;
  64. break;
  65. case '0810':// 9点 拉取日报明细
  66. Adjust::adjustReportViews(7) ;
  67. break;
  68. case '0001':// prodege 七日过岛120 人数
  69. Adjust::prodegeSpend() ;
  70. break;
  71. case '0005':// asaction 七日过岛100 人数
  72. Adjust::adActionSpend() ;
  73. break;
  74. case '0740':// Mistplay 花费
  75. Adjust::mistplaySpend() ;
  76. case '0745':// adjoe 花费
  77. Adjust::adjoeSpend() ;
  78. break;
  79. case '0035':// digitalturbine 花费
  80. Adjust::digitalturbineSpend() ;
  81. break;
  82. }
  83. Class Adjust{
  84. static $headers = [
  85. 'Authorization:Bearer '.API_TOKEN
  86. ];
  87. static $channelDateEvents = [
  88. 'adaction' => [ //adaction 7 天100 岛 20刀
  89. '2022-12-01' => [
  90. 'passisland100_d7_events_cohort' => 20
  91. ],
  92. ],
  93. 'prodege' => [ // Prodege多了一个链接 然后这个月开始事件改了哈 改成了20天内过120岛 给35刀,过200岛 给50刀,也就是说两个20天内 两个事件都过得话 就是85刀
  94. '2022-12-01' => [
  95. 'passisland120_d20_events_cohort' => 35,
  96. 'passisland200_d20_events_cohort' => 50,
  97. ],
  98. '2022-09-01' => [
  99. 'passisland120_d7_events_cohort' => 45,
  100. ],
  101. '2022-08-01' => [
  102. 'passisland20_d7_events_cohort' => 45 * 0.537542662,
  103. ],
  104. ],
  105. ];
  106. private static function getDateList($type, $maxNum = 120){
  107. $dayTime = strtotime(date('Y-m-d', TIMESTAMP));
  108. switch ($type){
  109. case 'day':
  110. $beginTime = $dayTime - 86400;
  111. break;
  112. case 'week':
  113. $maxNum = 52;
  114. $weekIdx = date('w', $dayTime);
  115. $weekIdx = empty($weekIdx) ? 7 : $weekIdx;
  116. $beginTime = $dayTime - ($weekIdx-1)*86400;
  117. break;
  118. case 'month':
  119. $maxNum = 13;
  120. $monthIdx = date('d', $dayTime);
  121. $beginTime = $dayTime - ($monthIdx-1)*86400;
  122. break;
  123. default:
  124. return[];
  125. }
  126. $dateList = [];
  127. for($i = 0; $i<= $maxNum; $i++){
  128. $stime = strtotime("-{$i} {$type}", $beginTime);
  129. $etime = strtotime("+1 {$type}", $stime) - 86400;
  130. $dateList[] = [date('Y-m-d', $stime), date('Y-m-d', $etime)];
  131. }
  132. return $dateList;
  133. }
  134. private static function getOldData($table, $date){
  135. $sql = "select * from {$table} where date = '{$date}'";
  136. $oldDatas = oo::commonOprDb(DB_CONN)->getAll($sql,MYSQLI_ASSOC);
  137. return $oldDatas;
  138. }
  139. # 周报,月报
  140. static function adjustReport($type = 'month'){
  141. $typePrefix = substr($type, 0, 1);
  142. $dateList = self::getDateList($type);
  143. $periodItemsPrefix = ['retained_users','paying_users','all_revenue_total','paying_user_size'];
  144. $periodDays = self::getPeriodIdxs($type);
  145. $periodItems = self::getPeriodItems($type);
  146. $adjustReportTable = otable::adjustReport($type);
  147. $dayCnt = 0;
  148. oo::commonOprDb(DB_CONN)->query("set names utf8mb4");
  149. foreach ($dateList as $dateArray){
  150. $insertAdjustData = [];
  151. $updateAdjustData = [];
  152. $dayCnt++;
  153. list($start, $end) = $dateArray;
  154. oo::logs()->debug3( "index:$dayCnt:{$start} ~ {$end}:" , 'adjustDataCrontab');
  155. $dateKey = $type == 'day' ? $start : date('Ymd', strtotime($start)) . '~'.date('Ymd', strtotime($end)) ;
  156. $params['date_period'] = "{$start}:{$end}";
  157. $params['dimensions'] = "country_code,network,tracker_token,os_name";
  158. $params['metrics'] = implode(',',$periodItems);
  159. $params['attribution_type'] = "click";
  160. // $params['reattributed'] = "false";
  161. $params['app_token__in'] = APP_TOKEN;
  162. $url = urldecode(API_URL . http_build_query($params));
  163. oo::logs()->debug3( $url , 'adjustDataCrontab');
  164. $response = funs::curlPost($url, self::$headers, [], 'GET');
  165. $response = @json_decode($response, true)['rows'] ?? [];
  166. oo::logs()->debug3( '记录数:' . count($response) , 'adjustDataCrontab');
  167. # 查询老数据
  168. $oldDatas = self::getOldData($adjustReportTable, $dateKey);
  169. $oldAdjustDataIdMaps = [];
  170. foreach ($oldDatas as $data){
  171. $key = "{$data['date']}{$data['countries']}{$data['os_names']}{$data['trackers_channel_token']}";
  172. $oldAdjustDataIdMaps[$key] = $data['id'];
  173. }
  174. $newkips = [0,0,0];
  175. foreach ($response as $data){
  176. $key = "{$dateKey}{$data['country_code']}{$data['os_name']}{$data['tracker_token']}";
  177. $adjustData = [
  178. 'date' => $dateKey,
  179. 'countries' => $data['country_code'],
  180. 'os_names' => $data['os_name'],
  181. 'trackers_channel_token' => $data['tracker_token'],
  182. 'trackers_channel_name' => $data['network'],
  183. 'trackers_group_type' => $data['network'],
  184. 'kpi_values' => json_encode([$data['daus'], $data['installs'], $data['all_revenue']],32),
  185. ];
  186. $periodData = [];
  187. foreach ($periodDays as $day){
  188. $kips = [];
  189. foreach ($periodItemsPrefix as $prefix){
  190. $kips[] = $data["{$prefix}_{$typePrefix}{$day}"];
  191. }
  192. $periodData[$day] = $kips;
  193. }
  194. $adjustData['period_values'] = json_encode($periodData);
  195. if(empty($oldAdjustDataIdMaps[$key])) # 新纪录
  196. $insertAdjustData[] = $adjustData;
  197. else
  198. $updateAdjustData[$oldAdjustDataIdMaps[$key]] = $adjustData;
  199. }
  200. oo::logs()->debug3( 'insertAdjustData:'.count($insertAdjustData), 'adjustDataCrontab');
  201. oo::logs()->debug3( 'updateAdjustData:'.count($updateAdjustData), 'adjustDataCrontab');
  202. if(count($insertAdjustData)){
  203. $insertAdjustDataList = array_chunk($insertAdjustData, 100);
  204. foreach ($insertAdjustDataList as $insertAdjustData){
  205. oo::commonOprDb(DB_CONN)->query(funs::db_intsertArrSQL($adjustReportTable, array_keys($insertAdjustData[0]), $insertAdjustData));
  206. }
  207. }
  208. foreach ($updateAdjustData as $id => $updateItem){
  209. oo::commonOprDb(DB_CONN)->query(funs::db_updateSQL($adjustReportTable, $updateItem, ' id='.$id));
  210. }
  211. oo::logs()->debug3( '--------------------------------------------------------------' , 'adjustDataCrontab');
  212. }
  213. oo::logs()->debug3( $dayCnt , 'adjustDataCrontab');
  214. }
  215. static function adjustReportViews($days = 120){
  216. ini_set('memory_limit', -1);
  217. $type = 'day';
  218. $typePrefix = substr($type, 0, 1);
  219. $dateList = self::getDateList($type, $days);
  220. $periodItemsPrefix = ['retained_users','paying_users','all_revenue_total','revenue_total'];
  221. $periodDays = [
  222. 0,
  223. 1,
  224. 2,
  225. 6,
  226. 14,
  227. 29,
  228. 59,
  229. 89,
  230. 119,
  231. ];
  232. $periodItems = self::getPeriodItems($type, $periodDays);
  233. $adjustViewsTable = otable::adjustPeriodViews();
  234. $dayCnt = 0;
  235. oo::commonOprDb(DB_CONN)->query("set names utf8mb4");
  236. $viewTracks = [];
  237. foreach (ViewChannels as $channel){
  238. $viewTracks = array_merge($viewTracks, (array)ChannelTrackMaps[$channel]);
  239. }
  240. foreach ($dateList as $dateArray){
  241. $insertAdjustData = [];
  242. $updateAdjustData = [];
  243. $dayCnt++;
  244. list($start, $end) = $dateArray;
  245. oo::logs()->debug3( "index:$dayCnt:{$start} ~ {$end}:" , 'adjustDataCrontab');
  246. // $dateKey = $type == 'day' ? $start : date('Ymd', strtotime($start)) . '~'.date('Ymd', strtotime($end)) ;
  247. $dateKey = $start;
  248. $params['date_period'] = "{$start}:{$end}";
  249. $params['dimensions'] = "channel,os_name,country_code,partner_name,adgroup_id_network,adgroup_network,creative_id_network,creative_network,campaign_id_network,campaign_network,network_token,campaign_token,adgroup_token,creative_token";
  250. $params['metrics'] = implode(',',$periodItems);
  251. $params['attribution_type'] = "click";
  252. $params['app_token__in'] = APP_TOKEN;
  253. $params['ad_revenue_sources'] = "Applovin+MAX+FB+only%2CAppLovin+Max";//&ad_revenue_sources=Applovin+MAX+FB+only%2CAppLovin+Max
  254. // $params['reattributed'] = "false";
  255. $url = urldecode(API_URL . http_build_query($params));
  256. oo::logs()->debug3( $url , 'adjustDataCrontab');
  257. $response = funs::curlPost($url, self::$headers, [], 'GET');
  258. $response = json_decode($response, true)['rows'] ?? [];
  259. oo::logs()->debug3( '记录数:' . count($response) , 'adjustDataCrontab');
  260. # 查询老数据
  261. $oldViewsDatas = self::getOldData($adjustViewsTable, $dateKey);
  262. $oldViewsDataIdMaps = [];
  263. foreach ($oldViewsDatas as $data){
  264. $key = "{$data['date']}{$data['countries']}{$data['os_names']}{$data['trackers_channel_token']}{$data['campaigns_token']}{$data['adgroups_token']}{$data['creatives_token']}";
  265. $oldViewsDataIdMaps[$key] = $data['id'];
  266. }
  267. foreach ($response as $data){
  268. if (!in_array($data['network_token'], $viewTracks))continue;
  269. if(empty($data['campaign_token']) || empty($data['adgroup_token']) || empty($data['creative_token']) )continue;
  270. $key = "{$dateKey}{$data['country_code']}{$data['os_name']}{$data['network_token']}{$data['campaign_token']}{$data['adgroup_token']}{$data['creative_token']}";
  271. $adjustData = [
  272. 'date' => $dateKey,
  273. 'trackers_channel_token' => $data['network_token'],
  274. 'trackers_channel_name' => $data['partner_name'],
  275. 'trackers_group_type' => $data['channel'],
  276. 'campaigns_token' => $data['campaign_token'],
  277. 'campaigns_name' => $data['campaign_network'],
  278. 'campaigns_id' => $data['campaign_id_network'],
  279. 'adgroups_token' => $data['adgroup_token'],
  280. 'adgroups_name' => $data['adgroup_network'],
  281. 'adgroups_id' => $data['adgroup_id_network'],
  282. 'creatives_token' => $data['creative_token'],
  283. 'creatives_name' => $data['creative_network'],
  284. 'creatives_id' => $data['creative_id_network'],
  285. 'countries' => $data['country_code'] ?? 'none',
  286. 'os_names' => $data['os_name'],
  287. 'kpi_values' => json_encode([$data['daus'], $data['installs'], $data['all_revenue'], $data['revenue']],32),
  288. ];
  289. foreach ($periodDays as $day){
  290. $kips = [];
  291. foreach ($periodItemsPrefix as $prefix){
  292. $kips[] = $data["{$prefix}_{$typePrefix}{$day}"];
  293. }
  294. $adjustData["period_{$day}_kpis"] = json_encode($kips);
  295. }
  296. if(empty($oldViewsDataIdMaps[$key])) # 新纪录
  297. $insertAdjustData[] = $adjustData;
  298. else
  299. $updateAdjustData[$oldViewsDataIdMaps[$key]] = $adjustData;
  300. }
  301. oo::logs()->debug3( 'insertAdjustData:'.count($insertAdjustData), 'adjustDataCrontab');
  302. oo::logs()->debug3( 'updateAdjustData:'.count($updateAdjustData), 'adjustDataCrontab');
  303. if(count($insertAdjustData)){
  304. $insertAdjustDataList = array_chunk($insertAdjustData, 500);
  305. foreach ($insertAdjustDataList as $insertAdjustData){
  306. oo::commonOprDb(DB_CONN)->query(funs::db_intsertArrSQL($adjustViewsTable, array_keys($insertAdjustData[0]), $insertAdjustData));
  307. }
  308. }
  309. foreach ($updateAdjustData as $id => $updateItem){
  310. oo::commonOprDb(DB_CONN)->query(funs::db_updateSQL($adjustViewsTable, $updateItem, ' id='.$id));
  311. }
  312. oo::logs()->debug3( '--------------------------------------------------------------' , 'adjustDataCrontab');
  313. }
  314. oo::logs()->debug3( $dayCnt , 'adjustDataCrontab');
  315. }
  316. static function adjustReportCampaign($days = 120){
  317. $type = 'day';
  318. $typePrefix = substr($type, 0, 1);
  319. $dateList = self::getDateList($type, $days);
  320. $periodItemsPrefix = ['retained_users','paying_users','all_revenue_total','revenue_total'];
  321. $periodDays = [
  322. 0,
  323. 1,
  324. 2,
  325. 6,
  326. 14,
  327. 29,
  328. 59,
  329. 89,
  330. 119,
  331. ];
  332. $periodItems = self::getPeriodItems($type, $periodDays);
  333. $adjustDataTable = otable::adjustPeriodCampaigns();
  334. $dayCnt = 0;
  335. oo::commonOprDb(DB_CONN)->query("set names utf8mb4");
  336. $viewTracks = [];
  337. foreach (ViewChannels as $channel){
  338. $viewTracks = array_merge($viewTracks, (array)ChannelTrackMaps[$channel]);
  339. }
  340. foreach ($dateList as $dateArray){
  341. $insertAdjustData = [];
  342. $updateAdjustData = [];
  343. $dayCnt++;
  344. list($start, $end) = $dateArray;
  345. oo::logs()->debug3( "index:$dayCnt:{$start} ~ {$end}:" , 'adjustDataCrontab');
  346. // $dateKey = $type == 'day' ? $start : date('Ymd', strtotime($start)) . '~'.date('Ymd', strtotime($end)) ;
  347. $dateKey = $start;
  348. $params['date_period'] = "{$start}:{$end}";
  349. $params['dimensions'] = "channel,os_name,country_code,partner_name,campaign_id_network,campaign_network,network_token,campaign_token";
  350. $params['metrics'] = implode(',',$periodItems);
  351. $params['attribution_type'] = "click";
  352. $params['app_token__in'] = APP_TOKEN;
  353. $params['ad_revenue_sources'] = "Applovin+MAX+FB+only%2CAppLovin+Max";//&ad_revenue_sources=Applovin+MAX+FB+only%2CAppLovin+Max
  354. // $params['reattributed'] = "false";
  355. $url = urldecode(API_URL . http_build_query($params));
  356. oo::logs()->debug3( $url , 'adjustDataCrontab');
  357. $response = funs::curlPost($url, self::$headers, [], 'GET');
  358. $response = @json_decode($response, true)['rows'] ?? [];
  359. oo::logs()->debug3( '记录数:' . count($response) , 'adjustDataCrontab');
  360. # 查询老数据
  361. $oldAdjustData = self::getOldData($adjustDataTable, $dateKey);
  362. $oldAdjustDataIdMaps = [];
  363. foreach ($oldAdjustData as $data){
  364. $key = "{$data['date']}{$data['countries']}{$data['os_names']}{$data['trackers_channel_token']}{$data['campaigns_token']}";
  365. $oldAdjustDataIdMaps[$key] = $data['id'];
  366. }
  367. foreach ($response as $data){
  368. if (in_array($data['network_token'], $viewTracks))continue;
  369. $key = "{$dateKey}{$data['country_code']}{$data['os_name']}{$data['network_token']}{$data['campaign_token']}";
  370. $adjustData = [
  371. 'date' => $dateKey,
  372. 'countries' => $data['country_code'] ?? 'none',
  373. 'os_names' => $data['os_name'],
  374. 'trackers_channel_token' => $data['network_token'],
  375. 'trackers_channel_name' => $data['partner_name'],
  376. 'trackers_group_type' => $data['channel'],
  377. 'campaigns_token' => $data['campaign_token'],
  378. 'campaigns_name' => $data['campaign_network'],
  379. 'campaigns_id' => $data['campaign_id_network'],
  380. 'kpi_values' => json_encode([$data['daus'], $data['installs'], $data['all_revenue'], $data['revenue']],32),// dau install 全部收入 内购收入
  381. ];
  382. foreach ($periodDays as $day){
  383. $kips = [];
  384. foreach ($periodItemsPrefix as $prefix){
  385. $kips[] = $data["{$prefix}_{$typePrefix}{$day}"];
  386. }
  387. $adjustData["period_{$day}_kpis"] = json_encode($kips);
  388. }
  389. if(empty($oldAdjustDataIdMaps[$key])) # 新纪录
  390. $insertAdjustData[] = $adjustData;
  391. else
  392. $updateAdjustData[$oldAdjustDataIdMaps[$key]] = $adjustData;
  393. }
  394. oo::logs()->debug3( 'insertAdjustData:'.count($insertAdjustData), 'adjustDataCrontab');
  395. oo::logs()->debug3( 'updateAdjustData:'.count($updateAdjustData), 'adjustDataCrontab');
  396. if(count($insertAdjustData)){
  397. $insertAdjustDataList = array_chunk($insertAdjustData, 500);
  398. foreach ($insertAdjustDataList as $insertAdjustData){
  399. oo::commonOprDb(DB_CONN)->query(funs::db_intsertArrSQL($adjustDataTable, array_keys($insertAdjustData[0]), $insertAdjustData));
  400. }
  401. }
  402. foreach ($updateAdjustData as $id => $updateItem){
  403. oo::commonOprDb(DB_CONN)->query(funs::db_updateSQL($adjustDataTable, $updateItem, ' id='.$id));
  404. }
  405. oo::logs()->debug3( '--------------------------------------------------------------' , 'adjustDataCrontab');
  406. }
  407. oo::logs()->debug3( $dayCnt , 'adjustDataCrontab');
  408. }
  409. private static function getPeriodIdxs($type){
  410. $periodDays = [];
  411. $max = 0;
  412. switch ($type){
  413. case 'day':
  414. $max = 120;
  415. break;
  416. case 'week':
  417. $max = 52;
  418. break;
  419. case 'month':
  420. $max = 13;
  421. break;
  422. default:
  423. return [];
  424. }
  425. for ($i=0;$i<=$max;$i++){
  426. if($type == 'week'){
  427. if($i > 1 && $i%4)continue;
  428. }
  429. $periodDays[] = $i;
  430. }
  431. return $periodDays;
  432. }
  433. private static function getPeriodItems($type, $periodDays = null){
  434. $periodItemsPrefix = ['retained_users','paying_users','all_revenue_total','revenue_total','paying_user_size'];
  435. $typePrefix = substr($type, 0, 1);
  436. $periodDays = $periodDays ?? self::getPeriodIdxs($type);
  437. $periodItems = ['daus','installs','cohort_all_revenue','all_revenue','revenue'];
  438. foreach ($periodItemsPrefix as $item){
  439. foreach ($periodDays as $day){
  440. $periodItems[] = "{$item}_{$typePrefix}{$day}";
  441. }
  442. }
  443. return $periodItems;
  444. }
  445. static function prodegeSpend(){
  446. $channel = 'prodege';
  447. $end = date('Y-m-d', TIMESTAMP - 20 * 86400);
  448. $start = $end;
  449. $table = otable::prodegeSpends();
  450. $events = array_keys(self::getEventsByChannelDate($channel, $start));
  451. $event = implode(',', $events);
  452. $query = "full_data=true&attribution_source=first&cost_mode=mixed&reattributed=all&attribution_type=all&readable_names=false&format_dates=false&metrics=installs,{$event}&dimensions=day&sort=day&utc_offset=%2B00:00&cohort_maturity=mature&sandbox=false&chart_1_dimensions=day&chart_1_metrics=installs&chart_2_dimensions=day&chart_2_metrics=installs&date_period={$start}:{$end}&channel_id__in=partner_1582&app_token__in=".APP_TOKEN;
  453. $url = API_URL . $query;
  454. oo::logs()->debug3( $url , 'adjustDataCrontab');
  455. $response = funs::curlPost($url, self::$headers, [], 'GET');
  456. $rows = @json_decode($response, true)['rows'] ?? [];
  457. oo::logs()->debug3( '记录数:' . count($rows) , 'adjustDataCrontab');
  458. $insertData = [];
  459. $deleteDates = [];
  460. foreach ($rows as $row){
  461. $deleteDates[] = $row['day'];
  462. $insertData[] = [
  463. 'date' => $row['day'],
  464. 'installs' => $row['installs'],
  465. 'spends' => self::getSpends($channel, $row),
  466. ];
  467. }
  468. $deleteDatesStr = implode("','", $deleteDates);
  469. oo::commonOprDb(DB_CONN)->query("delete from {$table} where date in ('{$deleteDatesStr}')");
  470. if (count($insertData)) oo::commonOprDb(DB_CONN)->query(funs::db_intsertArrSQL($table, array_keys($insertData[0]), $insertData));
  471. }
  472. static function adActionSpend($time = TIMESTAMP){
  473. $channel = 'adaction';
  474. $end = date('Y-m-d', $time - 7 * 86400);
  475. $start = $end;//date('Y-m-d', $time - 14 * 86400);
  476. $table = otable::adActionSpends();
  477. $events = array_keys(self::getEventsByChannelDate($channel, $start));
  478. $event = implode(',', $events);
  479. $query = "full_data=true&attribution_source=first&cost_mode=mixed&reattributed=all&attribution_type=all&readable_names=false&format_dates=false&metrics=installs,{$event}&dimensions=day&sort=day&utc_offset=%2B00:00&cohort_maturity=mature&sandbox=false&chart_1_dimensions=day&chart_1_metrics=installs&chart_2_dimensions=day&chart_2_metrics=installs&date_period={$start}:{$end}&channel_id__in=partner_234&app_token__in=".APP_TOKEN;
  480. $url = API_URL . $query;
  481. oo::logs()->debug3( $url , 'adjustDataCrontab');
  482. $response = funs::curlPost($url, self::$headers, [], 'GET');
  483. $rows = @json_decode($response, true)['rows'] ?? [];
  484. oo::logs()->debug3( '记录数:' . count($rows) , 'adjustDataCrontab');
  485. $insertData = [];
  486. $deleteDates = [];
  487. foreach ($rows as $row){
  488. $deleteDates[] = $row['day'];
  489. $insertData[] = [
  490. 'date' => $row['day'],
  491. 'installs' => $row['installs'],
  492. 'spends' => self::getSpends($channel, $row) ,
  493. ];
  494. }
  495. $deleteDatesStr = implode("','", $deleteDates);
  496. oo::commonOprDb(DB_CONN)->query("delete from {$table} where date in ('{$deleteDatesStr}')");
  497. if (count($insertData)) oo::commonOprDb(DB_CONN)->query(funs::db_intsertArrSQL($table, array_keys($insertData[0]), $insertData));
  498. }
  499. private static function getSpends($channel, array $row){
  500. $events = self::getEventsByChannelDate($channel, $row['day']);
  501. $spends = 0;
  502. foreach ($events as $event => $cpi){
  503. $spends += $row[$event] * floatval($cpi);
  504. }
  505. return $spends;
  506. }
  507. private static function getEventsByChannelDate($channel, $day){
  508. $channel = strtolower($channel);
  509. $channelEvents = self::$channelDateEvents[$channel] ?? [];
  510. if(empty($channelEvents))return [];
  511. foreach ($channelEvents as $date => $events){
  512. if($date <= $day){
  513. return $events;
  514. }
  515. }
  516. return $events;
  517. }
  518. static function mistplaySpend(){
  519. $table = otable::mistplaySpends();
  520. $end = date('Y-m-d', TIMESTAMP - 86400);
  521. $start = $end;
  522. $params = [
  523. 'full_data' => 'true',
  524. 'attribution_source' => 'first',
  525. 'cost_mode' => 'mixed',
  526. 'reattributed' => 'all',
  527. 'attribution_type' => 'all',
  528. 'readable_names' => 'false',
  529. 'format_dates' => 'false',
  530. 'metrics' => 'cost,installs',
  531. 'dimensions' => 'day',
  532. 'sort' => 'day',
  533. 'utc_offset' => urldecode('%2B00:00'),
  534. 'cohort_maturity' => 'mature',
  535. 'sandbox' => 'false',
  536. 'chart_1_dimensions' => 'day',
  537. 'chart_1_metrics' => 'installs',
  538. 'date_period' => "{$start}:{$end}",
  539. 'channel_id__in' => 'partner_1111',
  540. 'app_token__in' => APP_TOKEN,
  541. ];
  542. $query = http_build_query($params);
  543. $url = API_URL . $query;
  544. oo::logs()->debug3( 'request url:'.$url , 'adjustDataCrontab');
  545. $response = funs::curlPost($url, self::$headers, [], 'GET');
  546. $rows = @json_decode($response, true)['rows'] ?? [];
  547. oo::logs()->debug3( '记录数:' . count($rows) , 'adjustDataCrontab');
  548. $insertData = [];
  549. $deleteDates = [];
  550. foreach ($rows as $row){
  551. $deleteDates[] = $row['day'];
  552. $insertData[] = [
  553. 'date' => $row['day'],
  554. 'installs' => $row['installs'],
  555. 'spends' => $row['cost'],
  556. ];
  557. }
  558. $deleteDatesStr = implode("','", $deleteDates);
  559. oo::commonOprDb(DB_CONN)->query("delete from {$table} where date in ('{$deleteDatesStr}')");
  560. if (count($insertData)) oo::commonOprDb(DB_CONN)->query(funs::db_intsertArrSQL($table, array_keys($insertData[0]), $insertData));
  561. }
  562. static function adjoeSpend(){
  563. $table = otable::adjoeSpends();
  564. $end = date('Y-m-d', TIMESTAMP - 86400);
  565. $start = $end;
  566. $params = [
  567. 'full_data' => 'true',
  568. 'attribution_source' => 'first',
  569. 'cost_mode' => 'mixed',
  570. 'reattributed' => 'all',
  571. 'attribution_type' => 'all',
  572. 'readable_names' => 'false',
  573. 'format_dates' => 'false',
  574. 'metrics' => 'cost,installs',
  575. 'dimensions' => 'day',
  576. 'sort' => 'day',
  577. 'utc_offset' => urldecode('%2B00:00'),
  578. 'cohort_maturity' => 'mature',
  579. 'sandbox' => 'false',
  580. 'chart_1_dimensions' => 'day',
  581. 'chart_1_metrics' => 'installs',
  582. 'date_period' => "{$start}:{$end}",
  583. 'channel_id__in' => 'partner_1523',
  584. 'app_token__in' => APP_TOKEN,
  585. ];
  586. $query = http_build_query($params);
  587. $url = API_URL . $query;
  588. oo::logs()->debug3( 'request url:'.$url , 'adjustDataCrontab');
  589. $response = funs::curlPost($url, self::$headers, [], 'GET');
  590. $rows = @json_decode($response, true)['rows'] ?? [];
  591. oo::logs()->debug3( '记录数:' . count($rows) , 'adjustDataCrontab');
  592. $insertData = [];
  593. $deleteDates = [];
  594. foreach ($rows as $row){
  595. $deleteDates[] = $row['day'];
  596. $insertData[] = [
  597. 'date' => $row['day'],
  598. 'installs' => $row['installs'],
  599. 'spends' => $row['cost'],
  600. ];
  601. }
  602. $deleteDatesStr = implode("','", $deleteDates);
  603. oo::commonOprDb(DB_CONN)->query("delete from {$table} where date in ('{$deleteDatesStr}')");
  604. if (count($insertData)) oo::commonOprDb(DB_CONN)->query(funs::db_intsertArrSQL($table, array_keys($insertData[0]), $insertData));
  605. }
  606. static function digitalturbineSpend(){
  607. $tb = otable::digitalturbineSpends();
  608. $row = oo::commonOprDb(DB_CONN)->getOne("select * from {$tb} where id>0 limit 1");
  609. $end = date('Y-m-d', TIMESTAMP - 86400);
  610. if (empty($row)){
  611. $start = "2023-08-23";
  612. }else{
  613. $start = $end;
  614. }
  615. // 获取token
  616. $token = self::getDigitalturbineAccessToken();
  617. // 获取报告url
  618. $csvStr = self::getDigitalturbineReportData($token, $start, $end);
  619. if(empty($csvStr)){
  620. oo::logs()->debug3( "获取 digitalturbine 报告为空" , 'adjustDataCrontab');
  621. return;
  622. }
  623. $keysMapping = [
  624. "date" =>"date",
  625. "Country" =>"country",
  626. "Advertiser ARPU" =>"arpu",
  627. "Advertiser Spend" =>"spends",
  628. "Offer CTR" =>"ctr",
  629. "Offer Clicks" =>"clicks",
  630. "Offer Impressions" =>"impressions",
  631. "Offer Installs" =>'installs',
  632. "Campaign ID" =>'campaign_id',
  633. "Campaign Name" =>'campaign_name',
  634. "Device OS" =>'os',
  635. ];
  636. $csvStr = strtr($csvStr, ["\r\n" => "\n"]);
  637. $lines = explode("\n", $csvStr);
  638. $reportData = [];
  639. $keys = [];
  640. foreach ($lines as $line){
  641. $values = str_getcsv( $line);
  642. if(empty($keys)){
  643. foreach ($values as $k){
  644. $keys[] = $keysMapping[$k];
  645. }
  646. }else{
  647. if (count($keys) != count($values))continue;
  648. $reportData[] = array_combine($keys, $values);
  649. }
  650. }
  651. $reportData = array_filter($reportData);
  652. if (count($reportData))oo::commonOprDb(DB_CONN)->query(funs::db_intsertArrSQL($tb, $keys, $reportData));
  653. }
  654. private static function getDigitalturbineAccessToken(){
  655. $tokenUrl = 'https://reporting.fyber.com/auth/v1/token';
  656. $clientId = '0524e6d1d62825487a36ad567e88ff88';
  657. $clientSecret = '2D_oIp9qNVFyaGFuKxhY5l6wmT1aOBJcd91MXU5BXh26GdkpUYw5VOpkToBjWCQRau6c9ZKNPzk_C6dWDnAn7L0pbIdVg_4vLhFws2IxfS94JNdWgpDfStso1wqq9x_BpDRiT7UAw3SxeFWduH6OVsumkefQUGM-336EuJ242554QuJ0dJa0uo0SFTp7fif6fKL5FvXu2jDyP44pM4AcaMJBnUxfUUlDEdsHCxOWUb3EC8loqczgp_L6wK0viH3KwkqIzxsZ2sYAYgXmILv-B18hwCqL3gqnOhcqeYN0vwGuOCyoM5LF99TGw1yqRGyfRjNp5dD1k0Uptidtv6p5gg';
  658. $requestBody = [
  659. "grant_type" => "client_credentials",
  660. "client_id" => $clientId,
  661. "client_secret" => $clientSecret,
  662. ];
  663. $header = [
  664. 'Content-Type:application/json'
  665. ];
  666. $response = funs::curlPost($tokenUrl, $header, json_encode($requestBody), 'POST');
  667. oo::logs()->debug3( '获取 digitalturbine token 请求:'.json_encode($requestBody).' 响应:'.$response , 'adjustDataCrontab');
  668. if(is_string($response))$response = json_decode($response, true);
  669. if (empty($response['accessToken'])){
  670. return '';
  671. }
  672. return $response['accessToken'];
  673. }
  674. private static function getDigitalturbineReportData($accessToken, $start, $end){
  675. if(empty($accessToken)){
  676. return [];
  677. }
  678. $requestBody = [
  679. "source" =>"event",
  680. "dateRange" =>[
  681. "start" =>$start,
  682. "end" =>$end
  683. ],
  684. "metrics" =>[
  685. "Advertiser Spend",
  686. "Advertiser ARPU",
  687. "Offer Impressions",
  688. "Offer Clicks",
  689. "Offer CTR",
  690. "Offer Installs",
  691. ],
  692. "splits" =>[
  693. "Country",
  694. "Date",
  695. "Campaign ID",
  696. "Campaign Name",
  697. "Device OS",
  698. ],
  699. "filters" =>[
  700. // [
  701. // "dimension" =>"Country",
  702. // "values" =>[
  703. // "GB",
  704. // "US",
  705. // "DE"
  706. // ]
  707. // ]
  708. ]
  709. ];
  710. $header = [
  711. 'Content-Type:application/json',
  712. "Authorization: Bearer {$accessToken}"
  713. ];
  714. $url = 'https://reporting.fyber.com/api/v1/report/offerwall?format=csv';
  715. $response = funs::curlPost($url, $header, json_encode($requestBody), 'POST');
  716. oo::logs()->debug3( '获取 digitalturbine 报告url 请求:'.json_encode($requestBody).' 响应:'.$response , 'adjustDataCrontab');
  717. if(is_string($response))$response = json_decode($response, true);
  718. if (empty($response['url'])){
  719. return[];
  720. }
  721. sleep(6 * 60); // 等待对方文件生成
  722. return file_get_contents($response['url']);
  723. }
  724. }
  725. oo::logs()->debug3( "end:".time() , 'adjustDataCrontab');