[ 'fields' => 'account_id,campaign_id,campaign_name,spend,impressions,clicks,ctr,cpc,action_values,purchase_roas,date_start,date_stop', 'filtering_field' => 'campaign.effective_status' ], 'adset' => [ 'fields' => 'account_id,campaign_id,campaign_name,adset_id,adset_name,spend,impressions,clicks,ctr,cpc,action_values,purchase_roas,date_start,date_stop', 'filtering_field' => 'adset.effective_status' ], 'ad' => [ 'fields' => 'account_id,campaign_id,campaign_name,adset_id,adset_name,ad_id,ad_name,spend,impressions,clicks,ctr,cpc,action_values,purchase_roas,date_start,date_stop', 'filtering_field' => 'ad.effective_status' ] ]; $result = [ 'meta' => [ 'account_id' => $account_id, 'api_version' => $api_version, 'days' => $days, 'since' => $since, 'until' => $until, 'generated_at' => date( 'c' ) ], 'campaign' => [], 'adset' => [], 'ad' => [], 'summary' => [] ]; try { foreach ( $levels as $level => $cfg ) { fwrite( STDERR, "Fetching level: {$level}\n" ); $params = [ 'access_token' => $token, 'level' => $level, 'fields' => $cfg['fields'], 'time_increment' => 1, 'time_range' => json_encode( [ 'since' => $since, 'until' => $until ] ), 'filtering' => json_encode( [ [ 'field' => $cfg['filtering_field'], 'operator' => 'IN', 'value' => [ 'ACTIVE' ] ] ] ), 'limit' => 500 ]; $rows = fetch_all_pages( $base_url, $params ); $result[ $level ] = $rows; $result['summary'][ $level . '_rows' ] = count( $rows ); } } catch ( Exception $e ) { fwrite( STDERR, "Error: " . $e -> getMessage() . "\n" ); exit( 1 ); } $json = json_encode( $result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT ); if ( $json === false ) { fwrite( STDERR, "Failed to encode JSON output.\n" ); exit( 1 ); } if ( $output !== '' ) { $output_dir = dirname( $output ); if ( $output_dir !== '' && $output_dir !== '.' && !is_dir( $output_dir ) ) { if ( !mkdir( $output_dir, 0775, true ) && !is_dir( $output_dir ) ) { fwrite( STDERR, "Failed to create output directory: {$output_dir}\n" ); exit( 1 ); } } if ( file_put_contents( $output, $json ) === false ) { fwrite( STDERR, "Failed to write output file: {$output}\n" ); exit( 1 ); } fwrite( STDERR, "Saved: {$output}\n" ); } else { echo $json . PHP_EOL; } exit( 0 ); function fetch_all_pages( $url, $params = null ) { $all_rows = []; $next_url = $url; $next_params = $params; while ( $next_url ) { $payload = request_json( $next_url, $next_params ); if ( isset( $payload['data'] ) && is_array( $payload['data'] ) ) { foreach ( $payload['data'] as $row ) { $all_rows[] = $row; } } $next_url = ''; $next_params = null; if ( isset( $payload['paging']['next'] ) && is_string( $payload['paging']['next'] ) ) { $next_url = $payload['paging']['next']; } } return $all_rows; } function request_json( $url, $params = null ) { if ( is_array( $params ) ) { $query = http_build_query( $params ); $url .= ( strpos( $url, '?' ) === false ? '?' : '&' ) . $query; } $ch = curl_init( $url ); curl_setopt_array( $ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_CONNECTTIMEOUT => 20, CURLOPT_TIMEOUT => 120 ] ); $response = curl_exec( $ch ); $curl_error = curl_error( $ch ); $http_code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE ); curl_close( $ch ); if ( $response === false ) { throw new Exception( 'cURL error: ' . $curl_error ); } $decoded = json_decode( $response, true ); if ( !is_array( $decoded ) ) { throw new Exception( 'Invalid JSON response. HTTP ' . $http_code . '. Body: ' . substr( (string) $response, 0, 1000 ) ); } if ( isset( $decoded['error'] ) ) { $message = (string) ( $decoded['error']['message'] ?? 'Unknown API error' ); $code = (string) ( $decoded['error']['code'] ?? '' ); $subcode = (string) ( $decoded['error']['error_subcode'] ?? '' ); throw new Exception( 'Meta API error: ' . $message . ' (code: ' . $code . ', subcode: ' . $subcode . ')' ); } if ( $http_code >= 400 ) { throw new Exception( 'HTTP error ' . $http_code . '. Body: ' . substr( (string) $response, 0, 1000 ) ); } return $decoded; }