Report Requests Code Example

This example demonstrates how to request and retrieve performance reports.

using System;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.BingAds.V11.Reporting;
using Microsoft.BingAds;


namespace BingAdsExamplesLibrary.V11
{
    /// <summary>
    /// This example demonstrates how to request and retrieve performance reports
    /// using the ReportingServiceManager class.
    /// </summary>
    public class ReportRequests : ExampleBase
    {
        public static ReportingServiceManager ReportingServiceManager;

        /// <summary>
        /// The directory for the report file.
        /// </summary>
        protected const string FileDirectory = @"c:\reports\";
        
        /// <summary>
        /// The name of the report file.
        /// </summary>
        protected const string ResultFileName = @"result.csv";

        /// <summary>
        /// The report file extension type.
        /// </summary>
        protected const ReportFormat ReportFileFormat = ReportFormat.Csv;

        /// <summary>
        /// The maximum amount of time (in milliseconds) that you want to wait for the report download.
        /// </summary>
        protected const int TimeoutInMilliseconds = 360000;
        

        public override string Description
        {
            get { return "Report Requests | Reporting V11"; }
        }

        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ReportingServiceManager = new ReportingServiceManager(authorizationData);
                ReportingServiceManager.StatusPollIntervalInMilliseconds = 5000;

                // You can submit one of the example reports, or build your own.

                var reportRequest = GetAccountPerformanceReportRequest(authorizationData.AccountId);
                //var reportRequest = GetAdGroupPerformanceReportRequest(authorizationData.AccountId);
                //var reportRequest = GetAudiencePerformanceReportRequest(authorizationData.AccountId);
                //var reportRequest = GetBudgetSummaryReportRequest(authorizationData.AccountId);
                //var reportRequest = GetCampaignPerformanceReportRequest(authorizationData.AccountId);
                //var reportRequest = GetKeywordPerformanceReportRequest(authorizationData.AccountId);
                //var reportRequest = GetProductDimensionPerformanceReportRequest(authorizationData.AccountId);
                //var reportRequest = GetProductPartitionPerformanceReportRequest(authorizationData.AccountId);
                //var reportRequest = GetSearchCampaignChangeHistoryReportRequest(authorizationData.AccountId);

                var reportingDownloadParameters = new ReportingDownloadParameters
                {
                    ReportRequest = reportRequest,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName = ResultFileName,
                    OverwriteResultFile = true,
                };

                // Option A - Background Completion with ReportingServiceManager
                // You can submit a download request and the ReportingServiceManager will automatically 
                // return results. The ReportingServiceManager abstracts the details of checking for result file 
                // completion, and you don't have to write any code for results polling.

                OutputStatusMessage("Awaiting Background Completion . . .");
                await BackgroundCompletionAsync(reportingDownloadParameters);

                // Option B - Submit and Download with ReportingServiceManager
                // Submit the download request and then use the ReportingDownloadOperation result to 
                // track status until the report is complete e.g. either using
                // TrackAsync or GetStatusAsync.

                //OutputStatusMessage("Awaiting Submit and Download . . .");
                //await SubmitAndDownloadAsync(reportRequest);

                // Option C - Download Results with ReportingServiceManager
                // If for any reason you have to resume from a previous application state, 
                // you can use an existing download request identifier and use it 
                // to download the result file. 

                // For example you might have previously retrieved a request ID using SubmitDownloadAsync.
                //var reportingDownloadOperation = await ReportingService.SubmitDownloadAsync(reportRequest);
                //var requestId = reportingDownloadOperation.RequestId;

                // Given the request ID above, you can resume the workflow and download the report.
                // The report request identifier is valid for two days. 
                // If you do not download the report within two days, you must request the report again.
                //OutputStatusMessage("Awaiting Download Results . . .");
                //await DownloadResultsAsync(requestId, authorizationData);

            }
            // Catch authentication exceptions
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Reporting service exceptions
            catch (FaultException<Microsoft.BingAds.V11.Reporting.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(String.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException<Microsoft.BingAds.V11.Reporting.ApiFaultDetail> ex)
            {
                OutputStatusMessage(String.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(String.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (ReportingOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the reporting operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (ReportingOperationCouldNotBeCompletedException ex)
            {
                OutputStatusMessage(string.Format("ReportingOperationCouldNotBeCompletedException Message: {0}", ex.Message));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }

        /// <summary>
        /// You can submit a download request and the ReportingServiceManager will automatically
        /// return results. The ReportingServiceManager abstracts the details of checking for result file
        /// completion, and you don't have to write any code for results polling.
        /// </summary>
        /// <param name="reportingDownloadParameters"></param>
        private async Task BackgroundCompletionAsync(ReportingDownloadParameters reportingDownloadParameters)
        {
            // You may optionally cancel the DownloadFileAsync operation after a specified time interval. 
            var tokenSource = new CancellationTokenSource();
            tokenSource.CancelAfter(TimeoutInMilliseconds);

            var resultFilePath = await ReportingServiceManager.DownloadFileAsync(reportingDownloadParameters, tokenSource.Token);
            OutputStatusMessage(string.Format("Download result file: {0}\n", resultFilePath));
        }

        /// <summary>
        /// Submit the download request and then use the ReportingDownloadOperation result to 
        /// track status until the report is complete e.g. either using
        /// TrackAsync or GetStatusAsync.
        /// </summary>
        /// <param name="reportRequest"></param>
        /// <returns></returns>
        private async Task SubmitAndDownloadAsync(ReportRequest reportRequest)
        {
            // You may optionally cancel the TrackAsync operation after a specified time interval.  
            var tokenSource = new CancellationTokenSource();
            tokenSource.CancelAfter(TimeoutInMilliseconds);

            var reportingDownloadOperation = await ReportingServiceManager.SubmitDownloadAsync(reportRequest);

            ReportingOperationStatus reportingOperationStatus = await reportingDownloadOperation.TrackAsync(tokenSource.Token);
            
            // You can use TrackAsync to poll until complete as shown above, 
            // or use custom polling logic with GetStatusAsync as shown below.

            //ReportingOperationStatus reportingOperationStatus;

            //var waitTime = new TimeSpan(0, 0, 5);
            //for (int i = 0; i < 24; i++)
            //{
            //    Thread.Sleep(waitTime);

            //    reportingOperationStatus = await reportingDownloadOperation.GetStatusAsync();

            //    if (reportingOperationStatus.Status == ReportRequestStatusType.Success)
            //    {
            //        break;
            //    }
            //}

            var resultFilePath = await reportingDownloadOperation.DownloadResultFileAsync(
                FileDirectory,
                ResultFileName,
                decompress: true,
                overwrite: true);   // Set this value true if you want to overwrite the same file.

            OutputStatusMessage(string.Format("Download result file: {0}\n", resultFilePath));
        }

        /// <summary>
        /// If for any reason you have to resume from a previous application state, 
        /// you can use an existing download request identifier and use it 
        /// to download the result file. Use TrackAsync to indicate that the application 
        /// should wait to ensure that the download status is completed.
        /// </summary>
        /// <param name="requestId"></param>
        /// <param name="authorizationData"></param>
        /// <returns></returns>
        private async Task DownloadResultsAsync(
            string requestId,
            AuthorizationData authorizationData)
        {
            // You may optionally cancel the TrackAsync operation after a specified time interval. 
            var tokenSource = new CancellationTokenSource();
            tokenSource.CancelAfter(TimeoutInMilliseconds);

            var reportingDownloadOperation = new ReportingDownloadOperation(requestId, authorizationData);

            // Use TrackAsync to indicate that the application should wait to ensure that 
            // the download status is completed.
            var reportingOperationStatus = await reportingDownloadOperation.TrackAsync(tokenSource.Token);

            var resultFilePath = await reportingDownloadOperation.DownloadResultFileAsync(
                FileDirectory,
                ResultFileName,
                decompress: true,
                overwrite: true);   // Set this value true if you want to overwrite the same file.

            OutputStatusMessage(string.Format("Download result file: {0}", resultFilePath));
            OutputStatusMessage(string.Format("Status: {0}", reportingOperationStatus.Status));
            OutputStatusMessage(string.Format("TrackingId: {0}\n", reportingOperationStatus.TrackingId));
        }

        private KeywordPerformanceReportRequest GetKeywordPerformanceReportRequest(long accountId)
        {
            var report = new KeywordPerformanceReportRequest
            {
                Format = ReportFileFormat,
                Language = ReportLanguage.English,
                ReportName = "My Keyword Performance Report",
                ReturnOnlyCompleteData = false,
                Aggregation = ReportAggregation.Daily,

                Scope = new AccountThroughAdGroupReportScope
                {
                    AccountIds = new[] { accountId },
                    AdGroups = null,
                    Campaigns = null
                },

                Time = new ReportTime
                {
                    // You may either use a custom date range or predefined time.

                    CustomDateRangeStart = new Date
                    {
                        Month = 1,
                        Day = 1,
                        Year = DateTime.Now.Year - 1
                    },
                    CustomDateRangeEnd = new Date
                    {
                        Month = 12,
                        Day = 31,
                        Year = DateTime.Now.Year - 1
                    },

                    //PredefinedTime = ReportTimePeriod.Yesterday
                },

                // If you specify a filter, results may differ from data you see in the Bing Ads web application
                //Filter = new KeywordPerformanceReportFilter
                //{
                //    DeviceType = DeviceTypeReportFilter.Computer |
                //                 DeviceTypeReportFilter.SmartPhone
                //},

                // Specify the attribute and data report columns. 
                Columns = new[]
                {
                    KeywordPerformanceReportColumn.TimePeriod,
                    KeywordPerformanceReportColumn.AccountId,
                    KeywordPerformanceReportColumn.CampaignId,
                    KeywordPerformanceReportColumn.Keyword,
                    KeywordPerformanceReportColumn.KeywordId,
                    KeywordPerformanceReportColumn.DeviceType,
                    KeywordPerformanceReportColumn.BidMatchType,
                    KeywordPerformanceReportColumn.Clicks,
                    KeywordPerformanceReportColumn.Impressions,
                    KeywordPerformanceReportColumn.Ctr,
                    KeywordPerformanceReportColumn.AverageCpc,
                    KeywordPerformanceReportColumn.Spend,
                    KeywordPerformanceReportColumn.QualityScore,
                    KeywordPerformanceReportColumn.AdRelevance,
                    KeywordPerformanceReportColumn.LandingPageExperience,
                    KeywordPerformanceReportColumn.Revenue,
                    KeywordPerformanceReportColumn.Assists,
                    KeywordPerformanceReportColumn.ExpectedCtr,
                    KeywordPerformanceReportColumn.DeliveredMatchType,
                    KeywordPerformanceReportColumn.AveragePosition,
                    KeywordPerformanceReportColumn.Conversions,
                    KeywordPerformanceReportColumn.AdDistribution,
                    KeywordPerformanceReportColumn.Network,
                    KeywordPerformanceReportColumn.AdId,
                    KeywordPerformanceReportColumn.AdType,
                    KeywordPerformanceReportColumn.AdGroupId
                },

                // You may optionally sort by any KeywordPerformanceReportColumn, and optionally
                // specify the maximum number of rows to return in the sorted report. 
                Sort = new[]
                {
                    new KeywordPerformanceReportSort
                        {
                            SortColumn = KeywordPerformanceReportColumn.Clicks,
                            SortOrder = SortOrder.Ascending
                        }
                },

                MaxRows = 10,
            };

            return report;
        }

        private ReportRequest GetCampaignPerformanceReportRequest(long accountId)
        {
            var report = new CampaignPerformanceReportRequest
            {
                Format = ReportFileFormat,
                Language = ReportLanguage.English,
                ReportName = "My Campaign Performance Report",
                ReturnOnlyCompleteData = false,
                Aggregation = ReportAggregation.Daily,

                Scope = new AccountThroughCampaignReportScope
                {
                    AccountIds = new[] { accountId },
                    Campaigns = null
                },

                // Alternatively you can request data for a subset of campaigns.
                //Scope = new AccountThroughCampaignReportScope
                //{
                //    AccountIds = null,
                //    Campaigns = new [] {
                //        new CampaignReportScope
                //        {
                //            AccountId = accountId,
                //            CampaignId = <YourCampaignIdGoesHere>
                //        }
                //    }
                //},

                Time = new ReportTime
                {
                    // You may either use a custom date range or predefined time.

                    //CustomDateRangeStart = new Date
                    //{
                    //    Month = 1,
                    //    Day = 1,
                    //    Year = DateTime.Now.Year - 1
                    //},
                    //CustomDateRangeEnd = new Date
                    //{
                    //    Month = 12,
                    //    Day = 31,
                    //    Year = DateTime.Now.Year - 1
                    //},

                    PredefinedTime = ReportTimePeriod.Yesterday
                },

                // If you specify a filter, results may differ from data you see in the Bing Ads web application
                //Filter = new CampaignPerformanceReportFilter
                //{
                //    DeviceType = DeviceTypeReportFilter.Computer |
                //                 DeviceTypeReportFilter.SmartPhone
                //},

                // Specify the attribute and data report columns. 
                Columns = new[]
                {
                    CampaignPerformanceReportColumn.TimePeriod,
                    CampaignPerformanceReportColumn.AccountId,
                    CampaignPerformanceReportColumn.CampaignId,
                    CampaignPerformanceReportColumn.DeviceType,
                    CampaignPerformanceReportColumn.BidMatchType,
                    CampaignPerformanceReportColumn.QualityScore,
                    CampaignPerformanceReportColumn.AdRelevance,
                    CampaignPerformanceReportColumn.LandingPageExperience,
                    CampaignPerformanceReportColumn.Revenue,
                    CampaignPerformanceReportColumn.Assists,
                    CampaignPerformanceReportColumn.ExpectedCtr,
                    CampaignPerformanceReportColumn.DeliveredMatchType,
                    CampaignPerformanceReportColumn.AveragePosition,
                    CampaignPerformanceReportColumn.Conversions,
                    CampaignPerformanceReportColumn.AdDistribution,
                    CampaignPerformanceReportColumn.Network,
                    CampaignPerformanceReportColumn.Clicks,
                    CampaignPerformanceReportColumn.Impressions,
                    CampaignPerformanceReportColumn.Ctr,
                    CampaignPerformanceReportColumn.AverageCpc,
                    CampaignPerformanceReportColumn.Spend,
                    CampaignPerformanceReportColumn.LowQualityClicks,
                    CampaignPerformanceReportColumn.LowQualityConversionRate
                },

            };

            return report;
        }


        private ReportRequest GetAdGroupPerformanceReportRequest(long accountId)
        {
            var report = new AdGroupPerformanceReportRequest
            {
                Format = ReportFileFormat,
                Language = ReportLanguage.English,
                ReportName = "My Ad Group Performance Report",
                ReturnOnlyCompleteData = false,
                Aggregation = ReportAggregation.Daily,

                Scope = new AccountThroughAdGroupReportScope
                {
                    AccountIds = new[] { accountId },
                    Campaigns = null,
                    AdGroups = null
                },

               // Alternatively you can request data for a subset of campaigns or ad groups.
               //Scope = new AccountThroughAdGroupReportScope
               //{
               //    AccountIds = null,
               //    Campaigns = new[] {
               //         new AdGroupReportScope
               //         {
               //             AccountId = accountId,
               //             CampaignId = <YourCampaignIdGoesHere>,
               //             AdGroupId = <YourAdGroupIdGoesHere>
               //         }
               //    }
               //},

               Time = new ReportTime
                {
                    // You may either use a custom date range or predefined time.

                    //CustomDateRangeStart = new Date
                    //{
                    //    Month = 1,
                    //    Day = 1,
                    //    Year = DateTime.Now.Year - 1
                    //},
                    //CustomDateRangeEnd = new Date
                    //{
                    //    Month = 12,
                    //    Day = 31,
                    //    Year = DateTime.Now.Year - 1
                    //},

                    PredefinedTime = ReportTimePeriod.Yesterday
                },

                // If you specify a filter, results may differ from data you see in the Bing Ads web application
                //Filter = new AdGroupPerformanceReportFilter
                //{
                //    DeviceType = DeviceTypeReportFilter.Computer |
                //                 DeviceTypeReportFilter.SmartPhone
                //},

                // Specify the attribute and data report columns. 
                Columns = new[]
                {
                    AdGroupPerformanceReportColumn.TimePeriod,
                    AdGroupPerformanceReportColumn.AccountId,
                    AdGroupPerformanceReportColumn.CampaignId,
                    AdGroupPerformanceReportColumn.DeviceType,
                    AdGroupPerformanceReportColumn.BidMatchType,
                    AdGroupPerformanceReportColumn.QualityScore,
                    AdGroupPerformanceReportColumn.AdRelevance,
                    AdGroupPerformanceReportColumn.LandingPageExperience,
                    AdGroupPerformanceReportColumn.Revenue,
                    AdGroupPerformanceReportColumn.Assists,
                    AdGroupPerformanceReportColumn.ExpectedCtr,
                    AdGroupPerformanceReportColumn.DeliveredMatchType,
                    AdGroupPerformanceReportColumn.AveragePosition,
                    AdGroupPerformanceReportColumn.Conversions,
                    AdGroupPerformanceReportColumn.AdDistribution,
                    AdGroupPerformanceReportColumn.Network,
                    AdGroupPerformanceReportColumn.Clicks,
                    AdGroupPerformanceReportColumn.Impressions,
                    AdGroupPerformanceReportColumn.Ctr,
                    AdGroupPerformanceReportColumn.AverageCpc,
                    AdGroupPerformanceReportColumn.Spend,
                },

            };

            return report;
        }

        private ReportRequest GetAccountPerformanceReportRequest(long accountId)
        {
            var report = new AccountPerformanceReportRequest
            {
                Format = ReportFormat.Tsv,
                Language = ReportLanguage.English,
                ReportName = "My Account Performance Report",
                ReturnOnlyCompleteData = false,
                Aggregation = ReportAggregation.Weekly,

                Scope = new AccountReportScope
                {
                    AccountIds = new[] { accountId }
                },

                Time = new ReportTime
                {
                    // You may either use a custom date range or predefined time.

                    //CustomDateRangeStart = new Date
                    //    {
                    //        Month = DateTime.Now.Month,
                    //        Day = DateTime.Now.Day,
                    //        Year = DateTime.Now.Year - 1
                    //    },
                    //CustomDateRangeEnd = new Date
                    //    {
                    //    Month = DateTime.Now.Month,
                    //    Day = DateTime.Now.Day,
                    //    Year = DateTime.Now.Year
                    //    },

                    PredefinedTime = ReportTimePeriod.Yesterday
                },

                // If you specify a filter, results may differ from data you see in the Bing Ads web application
                //Filter = new AccountPerformanceReportFilter
                //{
                //    DeviceType = DeviceTypeReportFilter.Computer |
                //                 DeviceTypeReportFilter.SmartPhone
                //},

                // Specify the attribute and data report columns. 
                Columns = new[]
                {
                    AccountPerformanceReportColumn.TimePeriod,
                    AccountPerformanceReportColumn.AccountId,
                    AccountPerformanceReportColumn.DeviceType,
                    AccountPerformanceReportColumn.BidMatchType,
                    AccountPerformanceReportColumn.Revenue,
                    AccountPerformanceReportColumn.Assists,
                    AccountPerformanceReportColumn.DeliveredMatchType,
                    AccountPerformanceReportColumn.AveragePosition,
                    AccountPerformanceReportColumn.Conversions,
                    AccountPerformanceReportColumn.AdDistribution,
                    AccountPerformanceReportColumn.Network,
                    AccountPerformanceReportColumn.Clicks,
                    AccountPerformanceReportColumn.Impressions,
                    AccountPerformanceReportColumn.Ctr,
                    AccountPerformanceReportColumn.AverageCpc,
                    AccountPerformanceReportColumn.Spend,
                },

            };

            return report;
        }

        private ReportRequest GetBudgetSummaryReportRequest(long accountId)
        {
            var report = new BudgetSummaryReportRequest
            {
                Format = ReportFormat.Csv,
                Language = ReportLanguage.English,
                ReportName = "My Budget Summary Report",
                ReturnOnlyCompleteData = false,
                
                Scope = new AccountThroughCampaignReportScope
                {
                    AccountIds = new[] { accountId }
                },

                Time = new BudgetSummaryReportTime
                {
                    // You may either use a custom date range or predefined time.

                    //CustomDateRangeStart = new Date
                    //    {
                    //        Month = DateTime.Now.Month,
                    //        Day = DateTime.Now.Day,
                    //        Year = DateTime.Now.Year - 1
                    //    },
                    //CustomDateRangeEnd = new Date
                    //    {
                    //    Month = DateTime.Now.Month,
                    //    Day = DateTime.Now.Day,
                    //    Year = DateTime.Now.Year
                    //    },

                    PredefinedTime = BudgetSummaryReportTimePeriod.ThisMonth
                },
                
                // Specify the attribute and data report columns. 
                Columns = new[]
                {
                    BudgetSummaryReportColumn.Date,
                    BudgetSummaryReportColumn.MonthlyBudget,
                    BudgetSummaryReportColumn.DailySpend,
                    BudgetSummaryReportColumn.MonthToDateSpend,
                    BudgetSummaryReportColumn.AccountId,
                    BudgetSummaryReportColumn.AccountName,
                    BudgetSummaryReportColumn.AccountNumber,
                    BudgetSummaryReportColumn.CampaignId,
                    BudgetSummaryReportColumn.CampaignName,
                    BudgetSummaryReportColumn.CurrencyCode,
                },

            };

            return report;
        }

        private ReportRequest GetProductDimensionPerformanceReportRequest(long accountId)
        {
            return new ProductDimensionPerformanceReportRequest
            {
                Format = ReportFileFormat,
                ReportName = "My Product Dimension Performance Report",
                ReturnOnlyCompleteData = false,
                Aggregation = ReportAggregation.Daily,

                Scope = new AccountThroughAdGroupReportScope
                {
                    AccountIds = new[] { accountId },
                    AdGroups = null,
                    Campaigns = null
                },

                Time = new ReportTime
                {
                    // You may either use a custom date range or predefined time.

                    //CustomDateRangeStart = new Date
                    //{
                    //    Month = 1,
                    //    Day = 1,
                    //    Year = DateTime.Now.Year - 1
                    //},
                    //CustomDateRangeEnd = new Date
                    //{
                    //    Month = 12,
                    //    Day = 31,
                    //    Year = DateTime.Now.Year - 1
                    //},

                    PredefinedTime = ReportTimePeriod.Yesterday
                },

                // If you specify a filter, results may differ from data you see in the Bing Ads web application
                //Filter = new ProductDimensionPerformanceReportFilter
                //{
                //    DeviceType = DeviceTypeReportFilter.Computer |
                //                 DeviceTypeReportFilter.SmartPhone
                //},

                // Specify the attribute and data report columns. 
                Columns = new[]
                {
                    ProductDimensionPerformanceReportColumn.TimePeriod,
                    ProductDimensionPerformanceReportColumn.MerchantProductId,
                    ProductDimensionPerformanceReportColumn.AccountName,
                    ProductDimensionPerformanceReportColumn.AccountNumber,
                    ProductDimensionPerformanceReportColumn.AdGroupId,
                    ProductDimensionPerformanceReportColumn.AdGroupName,
                    ProductDimensionPerformanceReportColumn.AdId,
                    ProductDimensionPerformanceReportColumn.AverageCpc,
                    ProductDimensionPerformanceReportColumn.Brand,
                    ProductDimensionPerformanceReportColumn.CampaignName,
                    ProductDimensionPerformanceReportColumn.Condition,
                    ProductDimensionPerformanceReportColumn.Ctr,
                    ProductDimensionPerformanceReportColumn.CurrencyCode,
                    ProductDimensionPerformanceReportColumn.CustomLabel0,
                    ProductDimensionPerformanceReportColumn.CustomLabel1,
                    ProductDimensionPerformanceReportColumn.CustomLabel2,
                    ProductDimensionPerformanceReportColumn.CustomLabel3,
                    ProductDimensionPerformanceReportColumn.CustomLabel4,
                    ProductDimensionPerformanceReportColumn.DeviceType,
                    ProductDimensionPerformanceReportColumn.Language,
                    ProductDimensionPerformanceReportColumn.ProductCategory1,
                    ProductDimensionPerformanceReportColumn.ProductCategory2,
                    ProductDimensionPerformanceReportColumn.ProductCategory3,
                    ProductDimensionPerformanceReportColumn.ProductCategory4,
                    ProductDimensionPerformanceReportColumn.ProductCategory5,
                    ProductDimensionPerformanceReportColumn.ProductType1,
                    ProductDimensionPerformanceReportColumn.ProductType2,
                    ProductDimensionPerformanceReportColumn.ProductType3,
                    ProductDimensionPerformanceReportColumn.ProductType4,
                    ProductDimensionPerformanceReportColumn.ProductType5,
                    ProductDimensionPerformanceReportColumn.Spend,
                    ProductDimensionPerformanceReportColumn.Title,
                    ProductDimensionPerformanceReportColumn.Impressions,
                    ProductDimensionPerformanceReportColumn.Clicks,
                    ProductDimensionPerformanceReportColumn.Ctr,
                    ProductDimensionPerformanceReportColumn.AverageCpc,
                    ProductDimensionPerformanceReportColumn.Spend
                },
            };
        }

        private ReportRequest GetProductPartitionPerformanceReportRequest(long accountId)
        {
            return new ProductPartitionPerformanceReportRequest
            {
                Format = ReportFileFormat,
                ReportName = "My Product Partition Performance Report",
                ReturnOnlyCompleteData = false,
                Aggregation = ReportAggregation.Daily,

                Scope = new AccountThroughAdGroupReportScope
                {
                    AccountIds = new[] { accountId },
                    AdGroups = null,
                    Campaigns = null
                },

                Time = new ReportTime
                {
                    // You may either use a custom date range or predefined time.

                    //CustomDateRangeStart = new Date
                    //{
                    //    Month = 1,
                    //    Day = 1,
                    //    Year = DateTime.Now.Year - 1
                    //},
                    //CustomDateRangeEnd = new Date
                    //{
                    //    Month = 12,
                    //    Day = 31,
                    //    Year = DateTime.Now.Year - 1
                    //},

                    PredefinedTime = ReportTimePeriod.Yesterday
                },

                // If you specify a filter, results may differ from data you see in the Bing Ads web application
                //Filter = new ProductPartitionPerformanceReportFilter
                //{
                //    DeviceType = DeviceTypeReportFilter.Computer |
                //                 DeviceTypeReportFilter.SmartPhone
                //},

                // Specify the attribute and data report columns. 
                Columns = new[]
                {
                    ProductPartitionPerformanceReportColumn.TimePeriod,
                    ProductPartitionPerformanceReportColumn.AccountId,
                    ProductPartitionPerformanceReportColumn.CampaignId,
                    ProductPartitionPerformanceReportColumn.AdGroupCriterionId,
                    ProductPartitionPerformanceReportColumn.ProductGroup,
                    ProductPartitionPerformanceReportColumn.PartitionType,
                    ProductPartitionPerformanceReportColumn.BidMatchType,
                    ProductPartitionPerformanceReportColumn.Clicks,
                    ProductPartitionPerformanceReportColumn.Impressions,
                    ProductPartitionPerformanceReportColumn.Ctr,
                    ProductPartitionPerformanceReportColumn.AverageCpc,
                    ProductPartitionPerformanceReportColumn.Spend,
                },
            };
        }

        private ReportRequest GetAudiencePerformanceReportRequest(long accountId)
        {
            return new AudiencePerformanceReportRequest
            {
                Format = ReportFileFormat,
                ReportName = "My Audience Performance Report",
                ReturnOnlyCompleteData = false,
                Aggregation = ReportAggregation.Daily,

                Scope = new AccountThroughAdGroupReportScope
                {
                    AccountIds = new[] { accountId },
                    AdGroups = null,
                    Campaigns = null
                },

                Time = new ReportTime
                {
                    // You may either use a custom date range or predefined time.

                    //CustomDateRangeStart = new Date
                    //{
                    //    Month = 1,
                    //    Day = 1,
                    //    Year = DateTime.Now.Year - 1
                    //},
                    //CustomDateRangeEnd = new Date
                    //{
                    //    Month = 12,
                    //    Day = 31,
                    //    Year = DateTime.Now.Year - 1
                    //},

                    PredefinedTime = ReportTimePeriod.Yesterday
                },

                // Specify the attribute and data report columns. 
                Columns = new[]
                {
                    AudiencePerformanceReportColumn.TimePeriod,
                    AudiencePerformanceReportColumn.AccountId,
                    AudiencePerformanceReportColumn.CampaignId,
                    AudiencePerformanceReportColumn.AudienceId,
                    AudiencePerformanceReportColumn.AudienceName,
                    AudiencePerformanceReportColumn.BidAdjustment,
                    AudiencePerformanceReportColumn.TargetingSetting,
                    AudiencePerformanceReportColumn.Clicks,
                    AudiencePerformanceReportColumn.Impressions,
                    AudiencePerformanceReportColumn.Ctr,
                    AudiencePerformanceReportColumn.AverageCpc,
                    AudiencePerformanceReportColumn.Spend,
                },
            };
        }


        private ReportRequest GetSearchCampaignChangeHistoryReportRequest(long accountId)
        {
            var report = new SearchCampaignChangeHistoryReportRequest
            {
                Format = ReportFileFormat,
                Language = ReportLanguage.English,
                ReportName = "My Change History Performance Report",
                ReturnOnlyCompleteData = false,

                Scope = new AccountThroughAdGroupReportScope
                {
                    AccountIds = new[] { accountId },
                    AdGroups = null,
                    Campaigns = null
                },

                Time = new ReportTime
                {
                    // You may either use a custom date range or predefined time.

                    //CustomDateRangeStart = new Date
                    //{
                    //    Month = 1,
                    //    Day = 1,
                    //    Year = DateTime.Now.Year - 1
                    //},
                    //CustomDateRangeEnd = new Date
                    //{
                    //    Month = 12,
                    //    Day = 31,
                    //    Year = DateTime.Now.Year - 1
                    //},

                    PredefinedTime = ReportTimePeriod.LastThreeMonths
                },

                // If you specify a filter, results may differ from data you see in the Bing Ads web application
                //Filter = new SearchCampaignChangeHistoryReportFilter
                //{
                //    AdDistribution = AdDistributionReportFilter.Search | 
                //                     AdDistributionReportFilter.Native
                //},

                // Specify the attribute and data report columns. 
                Columns = new[]
                {
                    SearchCampaignChangeHistoryReportColumn.DateTime,
                    SearchCampaignChangeHistoryReportColumn.AccountId,
                    SearchCampaignChangeHistoryReportColumn.AdGroupId,
                    SearchCampaignChangeHistoryReportColumn.AdGroupName,
                    SearchCampaignChangeHistoryReportColumn.AdTitle,
                    SearchCampaignChangeHistoryReportColumn.AttributeChanged,
                    SearchCampaignChangeHistoryReportColumn.CampaignId,
                    SearchCampaignChangeHistoryReportColumn.CampaignName,
                    SearchCampaignChangeHistoryReportColumn.ChangedBy,
                    SearchCampaignChangeHistoryReportColumn.DisplayUrl,
                    SearchCampaignChangeHistoryReportColumn.HowChanged,
                    SearchCampaignChangeHistoryReportColumn.ItemChanged,
                    SearchCampaignChangeHistoryReportColumn.Keyword,
                    SearchCampaignChangeHistoryReportColumn.NewValue,
                    SearchCampaignChangeHistoryReportColumn.OldValue,
                },
                
            };

            return report;
        }

    }
}
package com.microsoft.bingads.examples.v11;

import java.util.Calendar;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.net.*;
import java.io.*;

import com.microsoft.bingads.*;
import com.microsoft.bingads.PasswordAuthentication;
import com.microsoft.bingads.v11.reporting.AdApiError;
import com.microsoft.bingads.v11.reporting.AdApiFaultDetail_Exception;
import com.microsoft.bingads.v11.reporting.ApiFaultDetail_Exception;
import com.microsoft.bingads.v11.reporting.BatchError;
import com.microsoft.bingads.v11.reporting.OperationError;
import com.microsoft.bingads.v11.reporting.*;

public class ReportRequests extends ExampleBase {

    static AuthorizationData authorizationData;
    static ReportingServiceManager ReportingServiceManager; 
    
    /*private static java.lang.String UserName = "<UserNameGoesHere>";
    private static java.lang.String Password = "<PasswordGoesHere>";
    private static java.lang.String DeveloperToken = "<DeveloperTokenGoesHere>";
    private static long CustomerId = <CustomerIdGoesHere>;
    private static long AccountId = <AccountIdGoesHere>; ;*/
        
    // The directory for the report file.
    static java.lang.String FileDirectory = "c:\\reports\\";

    // The name of the report file.
    static java.lang.String ResultFileName = "result";
    
    // The report file extension type.
    static ReportFormat ReportFileFormat = ReportFormat.CSV; 
    
    // The maximum amount of time (in milliseconds) that you want to wait for the report download.
    static int TimeoutInMilliseconds = 3600000;

    public static void main(String[] args) {
        
    	// Confirm that the download folder exists; otherwise, exit.
    	
    	String folder = FileDirectory.substring(0, FileDirectory.lastIndexOf('\\'));
        File dir = new File(folder);

        if (!dir.exists())
        {
            System.out.println("The output folder does not exist. Ensure that the " +
                "folder exists and try again.");
            return;
        }

        try
        {
            authorizationData = new AuthorizationData();
            authorizationData.setDeveloperToken(DeveloperToken);
            authorizationData.setAuthentication(new PasswordAuthentication(UserName, Password));
            authorizationData.setCustomerId(CustomerId);
            authorizationData.setAccountId(AccountId);
	         
            ReportingServiceManager = new ReportingServiceManager(authorizationData, API_ENVIRONMENT);
            ReportingServiceManager.setStatusPollIntervalInMilliseconds(5000);

            // You can submit one of the example reports, or build your own.
            ReportRequest reportRequest = getKeywordPerformanceReportRequest();

            ReportingDownloadParameters reportingDownloadParameters = new ReportingDownloadParameters();
            reportingDownloadParameters.setReportRequest(reportRequest);
            reportingDownloadParameters.setResultFileDirectory(new File(FileDirectory));
            reportingDownloadParameters.setResultFileName(ResultFileName);
            reportingDownloadParameters.setOverwriteResultFile(true);
                        
            // Option A - Background Completion with ReportingServiceManager
            // You can submit a download request and the ReportingServiceManager will automatically 
            // return results. The ReportingServiceManager abstracts the details of checking for result file 
            // completion, and you don't have to write any code for results polling.

            outputStatusMessage("Awaiting Background Completion . . .");
            backgroundCompletionAsync(reportingDownloadParameters);

            // Option B - Submit and Download with ReportingServiceManager
            // Submit the download request and then use the ReportingDownloadOperation result to 
            // track status until the report is complete e.g. either using
            // trackAsync or getStatusAsync.

            outputStatusMessage("Awaiting Submit and Download . . .");
            submitAndDownloadAsync(reportRequest);

            // Option C - Download Results with ReportingServiceManager
            // If for any reason you have to resume from a previous application state, 
            // you can use an existing download request identifier and use it 
            // to download the result file. 

            // For example you might have previously retrieved a request ID using submitDownloadAsync.
            ReportingDownloadOperation reportingDownloadOperation = 
            		ReportingServiceManager.submitDownloadAsync(reportRequest, null).get();
            java.lang.String requestId = reportingDownloadOperation.getRequestId();

            // Given the request ID above, you can resume the workflow and download the report.
            // The report request identifier is valid for two days. 
            // If you do not download the report within two days, you must request the report again.
            outputStatusMessage("Awaiting Download Results . . .");
            downloadResultsAsync(requestId);
            
            outputStatusMessage("Program execution completed\n"); 
        
        } catch (ExecutionException ee) {
			Throwable cause = ee.getCause();
			if (cause instanceof AdApiFaultDetail_Exception) {
				AdApiFaultDetail_Exception ex = (AdApiFaultDetail_Exception)cause;
				outputStatusMessage("The operation failed with the following faults:\n");
				
				for (AdApiError error : ex.getFaultInfo().getErrors().getAdApiErrors())
				{
					outputStatusMessage("AdApiError\n");
					outputStatusMessage(String.format("Code: %d\nError Code: %s\nMessage: %s\n\n", 
							error.getCode(), error.getErrorCode(), error.getMessage()));
				}
			} else if (cause instanceof ApiFaultDetail_Exception) {
				ApiFaultDetail_Exception ex = (ApiFaultDetail_Exception)cause;
				outputStatusMessage("The operation failed with the following faults:\n");
				
				for (BatchError error : ex.getFaultInfo().getBatchErrors().getBatchErrors())
				{
					outputStatusMessage(String.format("BatchError at Index: %d\n", error.getIndex()));
					outputStatusMessage(String.format("Code: %d\nMessage: %s\n\n", error.getCode(), error.getMessage()));
				}
				
				for (OperationError error : ex.getFaultInfo().getOperationErrors().getOperationErrors())
				{
					outputStatusMessage("OperationError\n");
					outputStatusMessage(String.format("Code: %d\nMessage: %s\n\n", error.getCode(), error.getMessage()));
				}
			} else {
				ee.printStackTrace();	
			}
		} catch (OAuthTokenRequestException ex) {
			outputStatusMessage(String.format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", 
					ex.getDetails().getError(), ex.getDetails().getDescription()));
			ex.printStackTrace();
		} catch (ReportingOperationInProgressException ex) {
			outputStatusMessage("The result file for the reporting operation is not yet available for download.");
			ex.printStackTrace();
		} catch (ReportingOperationCouldNotBeCompletedException ex) {
			outputStatusMessage(String.format("ReportingOperationCouldNotBeCompletedException Message: {0}", ex.getMessage()));
			ex.printStackTrace();
		} catch (InterruptedException ex) {
			ex.printStackTrace();
		} catch (IOException ex) {
			ex.printStackTrace();
		} catch (URISyntaxException ex) {
			ex.printStackTrace();
		} catch (TimeoutException ex) {
			ex.printStackTrace();
		}
    }
    
    // You can submit a download request and the ReportingServiceManager will automatically 
    // return results. The ReportingServiceManager abstracts the details of checking for result file 
    // completion, and you don't have to write any code for results polling.
    private static void backgroundCompletionAsync(ReportingDownloadParameters reportingDownloadParameters) 
    		throws ExecutionException, InterruptedException, TimeoutException {
    	// You may optionally cancel the downloadFileAsync operation after a specified time interval.
        File resultFile = ReportingServiceManager.downloadFileAsync(
                        reportingDownloadParameters, 
                        null).get(TimeoutInMilliseconds, TimeUnit.MILLISECONDS);
        
        if(resultFile != null && resultFile.getName() != "")
        {
            outputStatusMessage(String.format("Download result file: %s\n", resultFile.getName()));
        }
        else
        {
            outputStatusMessage("No report data for the submitted request\n");
        }
    }
    
    // Submit the download request and then use the ReportingDownloadOperation result to 
    // track status until the report is complete e.g. either using
    // trackAsync or getStatusAsync.
    private static void submitAndDownloadAsync(ReportRequest reportRequest) 
        throws ExecutionException, InterruptedException, URISyntaxException, IOException, TimeoutException {
        ReportingDownloadOperation reportingDownloadOperation = ReportingServiceManager.submitDownloadAsync(
                        reportRequest,
                        null).get();

        // You may optionally cancel the trackAsync operation after a specified time interval.
        ReportingOperationStatus reportingOperationStatus = 
                        reportingDownloadOperation.trackAsync(null).get(TimeoutInMilliseconds, TimeUnit.MILLISECONDS);

        // You can use trackAsync to poll until complete as shown above, 
        // or use custom polling logic with getStatusAsync as shown below.

//		ReportingOperationStatus reportingOperationStatus;
//		
//		for (int i = 0; i < 24; i++)
//		{
//		    Thread.sleep(5000);
//		    reportingOperationStatus = reportingDownloadOperation.getStatusAsync(null).get(TimeoutInMilliseconds, TimeUnit.MILLISECONDS);
//		    if (reportingOperationStatus.getStatus() == ReportRequestStatusType.SUCCESS)
//		    {
//		        break;
//		    }
//		}

        File resultFile = reportingDownloadOperation.downloadResultFileAsync(
            new File(FileDirectory),
            ResultFileName,
            true, // Set this value to true if you want to decompress the ZIP file.
            true,  // Set this value true if you want to overwrite the named file.
            null).get();
	
        if(resultFile != null && resultFile.getName() != "")
        {
            outputStatusMessage(String.format("Download result file: %s\n", resultFile.getName()));
        }
        else
        {
            outputStatusMessage("No report data for the submitted request\n");
        }
    }
    
    // If for any reason you have to resume from a previous application state, 
    // you can use an existing download request identifier and use it 
    // to download the result file. Use trackAsync to indicate that the application 
    // should wait to ensure that the download status is completed.
    private static void downloadResultsAsync(java.lang.String requestId) 
        throws ExecutionException, InterruptedException, URISyntaxException, IOException, TimeoutException {

        ReportingDownloadOperation reportingDownloadOperation = new ReportingDownloadOperation(requestId, authorizationData, API_ENVIRONMENT);

        reportingDownloadOperation.setStatusPollIntervalInMilliseconds(5000);

        // You can use trackAsync to poll until complete as shown here, 
    // or use custom polling logic with getStatusAsync.

        // You may optionally cancel the trackAsync operation after a specified time interval.
        ReportingOperationStatus reportingOperationStatus = 
                        reportingDownloadOperation.trackAsync(null).get(TimeoutInMilliseconds, TimeUnit.MILLISECONDS);

        File resultFile = reportingDownloadOperation.downloadResultFileAsync(
            new File(FileDirectory),
            ResultFileName,
            true, // Set this value to true if you want to decompress the ZIP file
            true,  // Set this value true if you want to overwrite the named file.
            null).get();

        if(resultFile != null && resultFile.getName() != "")
        {
            outputStatusMessage(String.format("Download result file: %s", resultFile.getName()));
            outputStatusMessage(String.format("Status: %s", reportingOperationStatus.getStatus()));
            outputStatusMessage(String.format("TrackingId: %s\n", reportingOperationStatus.getTrackingId()));
        }
        else
        {
            outputStatusMessage("No report data for the submitted request\n");
        }
    }

    private static ReportRequest getKeywordPerformanceReportRequest(){
    	KeywordPerformanceReportRequest report = new KeywordPerformanceReportRequest();
        
        report.setFormat(ReportFileFormat);
        report.setReportName("My Keyword Performance Report");
        report.setReturnOnlyCompleteData(false);
        report.setAggregation(ReportAggregation.DAILY);

        ArrayOflong accountIds = new ArrayOflong();
        accountIds.getLongs().add(authorizationData.getAccountId());
        
        report.setScope(new AccountThroughAdGroupReportScope());
        report.getScope().setAccountIds(accountIds);
        report.getScope().setCampaigns(null);
        report.getScope().setAdGroups(null);         

        report.setTime(new ReportTime());
        report.getTime().setPredefinedTime(ReportTimePeriod.YESTERDAY);
        
        // You may either use a custom date range or predefined time.
		//Calendar calendar = Calendar.getInstance();
        //report.getTime().setCustomDateRangeStart(new Date());
        //report.getTime().getCustomDateRangeStart().setMonth(1);
        //report.getTime().getCustomDateRangeStart().setDay(1);
        //report.getTime().getCustomDateRangeStart().setYear(calendar.get(Calendar.YEAR)-1);
        //report.getTime().setCustomDateRangeEnd(new Date());
        //report.getTime().getCustomDateRangeEnd().setMonth(12);
        //report.getTime().getCustomDateRangeEnd().setDay(31);
        //report.getTime().getCustomDateRangeEnd().setYear(calendar.get(Calendar.YEAR)-1);
        
        // If you specify a filter, results may differ from data you see in the Bing Ads web application
        //report.setFilter(new KeywordPerformanceReportFilter());
        //ArrayList<DeviceTypeReportFilter> deviceTypes = new ArrayList<DeviceTypeReportFilter>();
        //deviceTypes.add(DeviceTypeReportFilter.COMPUTER);
        //deviceTypes.add(DeviceTypeReportFilter.SMART_PHONE);
        //report.getFilter().setDeviceType(deviceTypes);

        // Specify the attribute and data report columns.
        
        ArrayOfKeywordPerformanceReportColumn keywordPerformanceReportColumns = new ArrayOfKeywordPerformanceReportColumn();
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.TIME_PERIOD);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.ACCOUNT_ID);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.CAMPAIGN_ID);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.KEYWORD);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.KEYWORD_ID);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.DEVICE_TYPE);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.BID_MATCH_TYPE);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.CLICKS);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.IMPRESSIONS);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.CTR);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.AVERAGE_CPC);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.SPEND);
        keywordPerformanceReportColumns.getKeywordPerformanceReportColumns().add(KeywordPerformanceReportColumn.QUALITY_SCORE);
        report.setColumns(keywordPerformanceReportColumns);
        
        // You may optionally sort by any KeywordPerformanceReportColumn, and optionally
        // specify the maximum number of rows to return in the sorted report. 

        KeywordPerformanceReportSort keywordPerformanceReportSort = new KeywordPerformanceReportSort();
        keywordPerformanceReportSort.setSortColumn(KeywordPerformanceReportColumn.CLICKS);
        keywordPerformanceReportSort.setSortOrder(SortOrder.ASCENDING);
        ArrayOfKeywordPerformanceReportSort keywordPerformanceReportSorts = new ArrayOfKeywordPerformanceReportSort();
        keywordPerformanceReportSorts.getKeywordPerformanceReportSorts().add(keywordPerformanceReportSort);
        report.setSort(keywordPerformanceReportSorts);
        
        report.setMaxRows(10);
        
        return report;
    }
}
<?php

namespace Microsoft\BingAds\Samples\V11;

// For more information about installing and using the Bing Ads PHP SDK, 
// see https://go.microsoft.com/fwlink/?linkid=838593.

require_once "/../vendor/autoload.php";

include "/../AuthHelper.php";
include "/CustomerManagementHelper.php";
include "/ReportingHelper.php";

use SoapVar;
use SoapFault;
use Exception;

// Specify the Microsoft\BingAds\V11\Reporting classes that will be used.
use Microsoft\BingAds\V11\Reporting\ReportRequestStatusType;

// Specify the Microsoft\BingAds\Auth classes that will be used.
use Microsoft\BingAds\Auth\ServiceClient;
use Microsoft\BingAds\Auth\ServiceClientType;

// Specify the Microsoft\BingAds\Samples classes that will be used.
use Microsoft\BingAds\Samples\AuthHelper;
use Microsoft\BingAds\Samples\V11\CustomerManagementHelper;
use Microsoft\BingAds\Samples\V11\ReportingHelper;

$GLOBALS['AuthorizationData'] = null;
$GLOBALS['Proxy'] = null;
$GLOBALS['CustomerProxy'] = null; 
$GLOBALS['CampaignProxy'] = null; 

// Disable WSDL caching.

ini_set("soap.wsdl_cache_enabled", "0");
ini_set("soap.wsdl_cache_ttl", "0");

// Specify the file to download the report to. Because the file is
// compressed use the .zip file extension.

$DownloadPath = "c:\\reports\\keywordperf.zip";

// Confirm that the download folder exist; otherwise, exit.

$length = strrpos($DownloadPath, '\\');
$folder = substr($DownloadPath, 0, $length);

if (!is_dir($folder))
{
    printf("The output folder, %s, does not exist.\nEnsure that the " .
        "folder exists and try again.", $folder);
    return;
}

try
{
    // You should authenticate for Bing Ads production services with a Microsoft Account, 
    // instead of providing the Bing Ads username and password set. 
    
    //AuthHelper::AuthenticateWithOAuth();

    // However, authentication with a Microsoft Account is currently not supported in Sandbox,
    // so it is recommended that you set the UserName and Password in sandbox for testing.

    AuthHelper::AuthenticateWithUserName();

    $GLOBALS['CustomerProxy'] = new ServiceClient(ServiceClientType::CustomerManagementVersion11, $GLOBALS['AuthorizationData'], AuthHelper::GetApiEnvironment());

    // Set the GetUser request parameter to an empty user identifier to get the current 
    // authenticated Bing Ads user, and then search for all accounts the user may access.

    $user = CustomerManagementHelper::GetUser(null)->User;

    // For this example we'll use the first account.

    $accounts = CustomerManagementHelper::SearchAccountsByUserId($user->Id)->Accounts;
    $GLOBALS['AuthorizationData']->AccountId = $accounts->Account[0]->Id;
    $GLOBALS['AuthorizationData']->CustomerId = $accounts->Account[0]->ParentCustomerId;

    $GLOBALS['ReportingProxy'] = new ServiceClient(ServiceClientType::ReportingVersion11, $GLOBALS['AuthorizationData'], AuthHelper::GetApiEnvironment());

    // You can submit one of the example reports, or build your own.
    $report = ReportingHelper::GetAccountPerformanceReportRequest($GLOBALS['AuthorizationData']->AccountId);
    //$report = ReportingHelper::GetAudiencePerformanceReportRequest($GLOBALS['AuthorizationData']->AccountId);
    //$report = ReportingHelper::GetKeywordPerformanceReportRequest($GLOBALS['AuthorizationData']->AccountId);
    
    // SubmitGenerateReport helper method calls the corresponding Bing Ads service operation
    // to request the report identifier. The identifier is used to check report generation status
    // before downloading the report.
    
    $reportRequestId = ReportingHelper::SubmitGenerateReport($report)->ReportRequestId;
    
    printf("Report Request ID: %s\n\n", $reportRequestId);
    
    $waitTime = 30 * 1; 
    $reportRequestStatus = null;
    
    // This sample polls every 30 seconds up to 5 minutes.
    // In production you may poll the status every 1 to 2 minutes for up to one hour.
    // If the call succeeds, stop polling. If the call or 
    // download fails, the call throws a fault.
    
    for ($i = 0; $i < 10; $i++)
    {
    	sleep($waitTime);
    
    	// PollGenerateReport helper method calls the corresponding Bing Ads service operation
    	// to get the report request status.
    	
    	$reportRequestStatus = ReportingHelper::PollGenerateReport($reportRequestId)->ReportRequestStatus;
    
    	if ($reportRequestStatus->Status == ReportRequestStatusType::Success ||
    		$reportRequestStatus->Status == ReportRequestStatusType::Error)
    	{
    		break;
    	}
    }

    if ($reportRequestStatus != null)
    {
    	if ($reportRequestStatus->Status == ReportRequestStatusType::Success)
    	{
            $reportDownloadUrl = $reportRequestStatus->ReportDownloadUrl;
            
            if($reportDownloadUrl == null)
            {
                print "No report data for the submitted request\n";
            }
            else
            {
                printf("Downloading from %s.\n\n", $reportDownloadUrl);
                DownloadFile($reportDownloadUrl, $DownloadPath);
                printf("The report was written to %s.\n", $DownloadPath);
            }
    		
    	}
    	else if ($reportRequestStatus->Status == ReportRequestStatusType::Error)
    	{
    		printf("The request failed. Try requesting the report " .
    				"later.\nIf the request continues to fail, contact support.\n");
    	}
    	else  // Pending
    	{
    		printf("The request is taking longer than expected.\n " .
    				"Save the report ID (%s) and try again later.\n",
    				$reportRequestId);
    	}
    }
    
}
catch (SoapFault $e)
{
    // Output the last request/response.

	print "\nLast SOAP request/response:\n";
    printf("Fault Code: %s\nFault String: %s\n", $e->faultcode, $e->faultstring);
	print $GLOBALS['Proxy']->GetWsdl() . "\n";
	print $GLOBALS['Proxy']->GetService()->__getLastRequest()."\n";
	print $GLOBALS['Proxy']->GetService()->__getLastResponse()."\n";
	 
	// Reporting service operations can throw AdApiFaultDetail.
	if (isset($e->detail->AdApiFaultDetail))
	{
		// Log this fault.

		print "The operation failed with the following faults:\n";

		$errors = is_array($e->detail->AdApiFaultDetail->Errors->AdApiError)
		? $e->detail->AdApiFaultDetail->Errors->AdApiError
		: array('AdApiError' => $e->detail->AdApiFaultDetail->Errors->AdApiError);

		// If the AdApiError array is not null, the following are examples of error codes that may be found.
		foreach ($errors as $error)
		{
			print "AdApiError\n";
			printf("Code: %d\nError Code: %s\nMessage: %s\n", $error->Code, $error->ErrorCode, $error->Message);

			switch ($error->Code)
			{
				case 0:    // InternalError
					break;
				case 105:  // InvalidCredentials
					break;
				default:
					print "Please see MSDN documentation for more details about the error code output above.\n";
					break;
			}
		}
	}

	// Reporting service operations can throw ApiFaultDetail.
	elseif (isset($e->detail->ApiFaultDetail))
	{
		// Log this fault.

		print "The operation failed with the following faults:\n";

		// If the BatchError array is not null, the following are examples of error codes that may be found.
		if (!empty($e->detail->ApiFaultDetail->BatchErrors))
		{
			$errors = is_array($e->detail->ApiFaultDetail->BatchErrors->BatchError)
			? $e->detail->ApiFaultDetail->BatchErrors->BatchError
			: array('BatchError' => $e->detail->ApiFaultDetail->BatchErrors->BatchError);

			foreach ($errors as $error)
			{
				printf("BatchError at Index: %d\n", $error->Index);
				printf("Code: %d\nError Code: %s\nMessage: %s\n", $error->Code, $error->ErrorCode, $error->Message);

				switch ($error->Code)
				{
					case 0:     // InternalError
						break;
					default:
						print "Please see MSDN documentation for more details about the error code output above.\n";
						break;
				}
			}
		}

		// If the OperationError array is not null, the following are examples of error codes that may be found.
		if (!empty($e->detail->ApiFaultDetail->OperationErrors))
		{
			$errors = is_array($e->detail->ApiFaultDetail->OperationErrors->OperationError)
			? $e->detail->ApiFaultDetail->OperationErrors->OperationError
			: array('OperationError' => $e->detail->ApiFaultDetail->OperationErrors->OperationError);

			foreach ($errors as $error)
			{
				print "OperationError\n";
				printf("Code: %d\nError Code: %s\nMessage: %s\n", $error->Code, $error->ErrorCode, $error->Message);

				switch ($error->Code)
				{
					case 0:     // InternalError
						break;
					case 106:   // UserIsNotAuthorized
						break;
					case 2100:  // ReportingServiceInvalidReportId
						break;
					default:
						print "Please see MSDN documentation for more details about the error code output above.\n";
						break;
				}
			}
		}
	}
}
catch (Exception $e)
{
    if ($e->getPrevious())
    {
        ; // Ignore fault exceptions that we already caught.
    }
    else
    {
        print $e->getCode()." ".$e->getMessage()."\n\n";
        print $e->getTraceAsString()."\n\n";
    }
}

// Using the URL that the PollGenerateReport operation returned,
// send an HTTP request to get the report and write it to the specified
// ZIP file.

function DownloadFile($reportDownloadUrl, $downloadPath)
{
    if (!$reader = fopen($reportDownloadUrl, 'rb'))
    {
        throw new Exception("Failed to open URL " . $reportDownloadUrl . ".");
    }

    if (!$writer = fopen($downloadPath, 'wb'))
    {
        fclose($reader);
        throw new Exception("Failed to create ZIP file " . $downloadPath . ".");
    }

    $bufferSize = 100 * 1024;

    while (!feof($reader))
    {
        if (false === ($buffer = fread($reader, $bufferSize)))
        {
             fclose($reader);
             fclose($writer);
             throw new Exception("Read operation from URL failed.");
        }

        if (fwrite($writer, $buffer) === false)
        {
             fclose($reader);
             fclose($writer);
             $exception = new Exception("Write operation to ZIP file failed.");
        }
    }

    fclose($reader);
    fflush($writer);
    fclose($writer);
}

?>
from auth_helper import *
from output_helper import *

# You must provide credentials in auth_helper.py.

# The directory for the report files.
FILE_DIRECTORY='c:/reports/'

# The name of the report download file.
DOWNLOAD_FILE_NAME='download.csv'

# The report file extension type.
REPORT_FILE_FORMAT='Csv'

# The maximum amount of time (in milliseconds) that you want to wait for the report download.
TIMEOUT_IN_MILLISECONDS=3600000

def main(authorization_data):

    try:
        # You can submit one of the example reports, or build your own.

        #report_request=get_budget_summary_report_request()
        #report_request=get_user_location_performance_report_request()
        report_request=get_keyword_performance_report_request()
        
        reporting_download_parameters = ReportingDownloadParameters(
            report_request=report_request,
            result_file_directory = FILE_DIRECTORY, 
            result_file_name = DOWNLOAD_FILE_NAME, 
            overwrite_result_file = True, # Set this value true if you want to overwrite the same file.
            timeout_in_milliseconds=TIMEOUT_IN_MILLISECONDS # You may optionally cancel the download after a specified time interval.
        )

        #Option A - Background Completion with ReportingServiceManager
        #You can submit a download request and the ReportingServiceManager will automatically 
        #return results. The ReportingServiceManager abstracts the details of checking for result file 
        #completion, and you don't have to write any code for results polling.

        output_status_message("Awaiting Background Completion . . .");
        background_completion(reporting_download_parameters)

        #Option B - Submit and Download with ReportingServiceManager
        #Submit the download request and then use the ReportingDownloadOperation result to 
        #track status yourself using ReportingServiceManager.get_status().

        output_status_message("Awaiting Submit and Download . . .");
        submit_and_download(report_request)

        #Option C - Download Results with ReportingServiceManager
        #If for any reason you have to resume from a previous application state, 
        #you can use an existing download request identifier and use it 
        #to download the result file. 

        #For example you might have previously retrieved a request ID using submit_download.
        reporting_operation=reporting_service_manager.submit_download(report_request);
        request_id=reporting_operation.request_id;

        #Given the request ID above, you can resume the workflow and download the report.
        #The report request identifier is valid for two days. 
        #If you do not download the report within two days, you must request the report again.
        output_status_message("Awaiting Download Results . . .");
        download_results(request_id, authorization_data)

        output_status_message("Program execution completed")

    except WebFault as ex:
        output_webfault_errors(ex)
    except Exception as ex:
        output_status_message(ex)

def get_budget_summary_report_request():
    '''
    Build a budget summary report request, including Format, ReportName,
    Time, and Columns.
    '''
    report_request=reporting_service.factory.create('BudgetSummaryReportRequest')
    report_request.Format=REPORT_FILE_FORMAT
    report_request.ReportName='My Budget Summary Report'
    report_request.ReturnOnlyCompleteData=False
    report_request.Language='English'

    scope=reporting_service.factory.create('AccountThroughCampaignReportScope')
    scope.AccountIds={'long': [authorization_data.account_id] }
    scope.Campaigns=None
    report_request.Scope=scope

    report_time=reporting_service.factory.create('ReportTime')
    # You may either use a custom date range or predefined time.
    
    #custom_date_range_start=reporting_service.factory.create('Date')
    #custom_date_range_start.Day=1
    #custom_date_range_start.Month=1
    #custom_date_range_start.Year=int(strftime("%Y", gmtime()))-1
    #report_time.CustomDateRangeStart=custom_date_range_start
    #custom_date_range_end=reporting_service.factory.create('Date')
    #custom_date_range_end.Day=31
    #custom_date_range_end.Month=12
    #custom_date_range_end.Year=int(strftime("%Y", gmtime()))-1
    #report_time.CustomDateRangeEnd=custom_date_range_end
    #report_time.PredefinedTime=None
    
    report_time.PredefinedTime='Yesterday'
    report_request.Time=report_time

    # Specify the attribute and data report columns.

    report_columns=reporting_service.factory.create('ArrayOfBudgetSummaryReportColumn')
    report_columns.BudgetSummaryReportColumn.append([
        'AccountName',
        'AccountNumber',
        'CampaignName',
        'CurrencyCode',
        'Date',
        'DailySpend',
    ])
    report_request.Columns=report_columns

    return report_request

def get_keyword_performance_report_request():
    '''
    Build a keyword performance report request, including Format, ReportName, Aggregation,
    Scope, Time, Filter, and Columns.
    '''
    report_request=reporting_service.factory.create('KeywordPerformanceReportRequest')
    report_request.Format=REPORT_FILE_FORMAT
    report_request.ReportName='My Keyword Performance Report'
    report_request.ReturnOnlyCompleteData=False
    report_request.Aggregation='Daily'
    report_request.Language='English'

    scope=reporting_service.factory.create('AccountThroughAdGroupReportScope')
    scope.AccountIds={'long': [authorization_data.account_id] }
    scope.Campaigns=None
    scope.AdGroups=None
    report_request.Scope=scope

    report_time=reporting_service.factory.create('ReportTime')
    # You may either use a custom date range or predefined time.
    
    #custom_date_range_start=reporting_service.factory.create('Date')
    #custom_date_range_start.Day=1
    #custom_date_range_start.Month=1
    #custom_date_range_start.Year=int(strftime("%Y", gmtime()))-1
    #report_time.CustomDateRangeStart=custom_date_range_start
    #custom_date_range_end=reporting_service.factory.create('Date')
    #custom_date_range_end.Day=31
    #custom_date_range_end.Month=12
    #custom_date_range_end.Year=int(strftime("%Y", gmtime()))-1
    #report_time.CustomDateRangeEnd=custom_date_range_end
    #report_time.PredefinedTime=None
    
    report_time.PredefinedTime='Yesterday'
    report_request.Time=report_time

    # If you specify a filter, results may differ from data you see in the Bing Ads web application

    #report_filter=reporting_service.factory.create('KeywordPerformanceReportFilter')
    #report_filter.DeviceType=[
    #    'Computer',
    #    'SmartPhone'
    #]
    #report_request.Filter=report_filter

    # Specify the attribute and data report columns.

    report_columns=reporting_service.factory.create('ArrayOfKeywordPerformanceReportColumn')
    report_columns.KeywordPerformanceReportColumn.append([
        'TimePeriod',
        'AccountId',
        'CampaignId',
        'Keyword',
        'KeywordId',
        'DeviceType',
        'BidMatchType',
        'Clicks',
        'Impressions',
        'Ctr',
        'AverageCpc',
        'Spend',
        'QualityScore',
    ])
    report_request.Columns=report_columns

    # You may optionally sort by any KeywordPerformanceReportColumn, and optionally
    # specify the maximum number of rows to return in the sorted report. 

    report_sorts=reporting_service.factory.create('ArrayOfKeywordPerformanceReportSort')
    report_sort=reporting_service.factory.create('KeywordPerformanceReportSort')
    report_sort.SortColumn='Clicks'
    report_sort.SortOrder='Ascending'
    report_sorts.KeywordPerformanceReportSort.append(report_sort)
    report_request.Sort=report_sorts

    report_request.MaxRows=10

    return report_request

def get_user_location_performance_report_request():
    '''
    Build a geo location performance report request, including Format, ReportName, Aggregation,
    Scope, Time, Filter, and Columns.
    '''
    report_request=reporting_service.factory.create('UserLocationPerformanceReportRequest')
    report_request.Format=REPORT_FILE_FORMAT
    report_request.ReportName='My Geographic Performance Report'
    report_request.ReturnOnlyCompleteData=False
    report_request.Aggregation='Daily'
    report_request.Language='English'

    scope=reporting_service.factory.create('AccountThroughAdGroupReportScope')
    scope.AccountIds={'long': [authorization_data.account_id] }
    scope.Campaigns=None
    scope.AdGroups=None
    report_request.Scope=scope

    report_time=reporting_service.factory.create('ReportTime')
    # You may either use a custom date range or predefined time.
    
    #custom_date_range_start=reporting_service.factory.create('Date')
    #custom_date_range_start.Day=1
    #custom_date_range_start.Month=1
    #custom_date_range_start.Year=int(strftime("%Y", gmtime()))-1
    #report_time.CustomDateRangeStart=custom_date_range_start
    #custom_date_range_end=reporting_service.factory.create('Date')
    #custom_date_range_end.Day=31
    #custom_date_range_end.Month=12
    #custom_date_range_end.Year=int(strftime("%Y", gmtime()))-1
    #report_time.CustomDateRangeEnd=custom_date_range_end
    #report_time.PredefinedTime=None
    
    report_time.PredefinedTime='Yesterday'
    report_request.Time=report_time

    # If you specify a filter, results may differ from data you see in the Bing Ads web application

    report_filter=reporting_service.factory.create('UserLocationPerformanceReportFilter')
    country_codes=reporting_service.factory.create('ns1:ArrayOfstring')
    country_codes.string.append('US')
    report_filter.CountryCode=country_codes
    report_request.Filter=report_filter

    # Specify the attribute and data report columns.

    report_columns=reporting_service.factory.create('ArrayOfUserLocationPerformanceReportColumn')
    report_columns.UserLocationPerformanceReportColumn.append([
        'TimePeriod',
        'AccountId',
        'AccountName',
        'CampaignId',
        'AdGroupId',
        'LocationType',
        'Country',
        'Clicks',
        'Impressions',
        'Ctr',
        'AverageCpc',
        'Spend',
    ])
    report_request.Columns=report_columns

    return report_request

def background_completion(reporting_download_parameters):
    '''
    You can submit a download request and the ReportingServiceManager will automatically 
    return results. The ReportingServiceManager abstracts the details of checking for result file 
    completion, and you don't have to write any code for results polling.
    '''
    global reporting_service_manager
    result_file_path = reporting_service_manager.download_file(reporting_download_parameters)
    output_status_message("Download result file: {0}\n".format(result_file_path))

def submit_and_download(report_request):
    '''
    Submit the download request and then use the ReportingDownloadOperation result to 
    track status until the report is complete e.g. either using
    ReportingDownloadOperation.track() or ReportingDownloadOperation.get_status().
    '''
    global reporting_service_manager
    reporting_download_operation = reporting_service_manager.submit_download(report_request)

    # You may optionally cancel the track() operation after a specified time interval.
    reporting_operation_status = reporting_download_operation.track(timeout_in_milliseconds=TIMEOUT_IN_MILLISECONDS)

    # You can use ReportingDownloadOperation.track() to poll until complete as shown above, 
    # or use custom polling logic with get_status() as shown below.
    #for i in range(10):
    #    time.sleep(reporting_service_manager.poll_interval_in_milliseconds / 1000.0)

    #    download_status = reporting_download_operation.get_status()
        
    #    if download_status.status == 'Success':
    #        break
    
    result_file_path = reporting_download_operation.download_result_file(
        result_file_directory = FILE_DIRECTORY, 
        result_file_name = DOWNLOAD_FILE_NAME, 
        decompress = True, 
        overwrite = True,  # Set this value true if you want to overwrite the same file.
        timeout_in_milliseconds=TIMEOUT_IN_MILLISECONDS # You may optionally cancel the download after a specified time interval.
    )
    
    output_status_message("Download result file: {0}\n".format(result_file_path))

def download_results(request_id, authorization_data):
    '''
    If for any reason you have to resume from a previous application state, 
    you can use an existing download request identifier and use it 
    to download the result file. Use ReportingDownloadOperation.track() to indicate that the application 
    should wait to ensure that the download status is completed.
    '''
    reporting_download_operation = ReportingDownloadOperation(
        request_id = request_id, 
        authorization_data=authorization_data, 
        poll_interval_in_milliseconds=1000, 
        environment=ENVIRONMENT,
    )

    # Use track() to indicate that the application should wait to ensure that 
    # the download status is completed.
    # You may optionally cancel the track() operation after a specified time interval.
    reporting_operation_status = reporting_download_operation.track(timeout_in_milliseconds=TIMEOUT_IN_MILLISECONDS)
    
    result_file_path = reporting_download_operation.download_result_file(
        result_file_directory = FILE_DIRECTORY, 
        result_file_name = DOWNLOAD_FILE_NAME, 
        decompress = True, 
        overwrite = True,  # Set this value true if you want to overwrite the same file.
        timeout_in_milliseconds=TIMEOUT_IN_MILLISECONDS # You may optionally cancel the download after a specified time interval.
    ) 

    output_status_message("Download result file: {0}".format(result_file_path))
    output_status_message("Status: {0}\n".format(reporting_operation_status.status))

# Main execution
if __name__ == '__main__':

    print("Python loads the web service proxies at runtime, so you will observe " \
          "a performance delay between program launch and main execution...\n")
    
    authorization_data=AuthorizationData(
        account_id=None,
        customer_id=None,
        developer_token=DEVELOPER_TOKEN,
        authentication=None,
    )

    reporting_service_manager=ReportingServiceManager(
        authorization_data=authorization_data, 
        poll_interval_in_milliseconds=5000, 
        environment=ENVIRONMENT,
    )

    # In addition to ReportingServiceManager, you will need a reporting ServiceClient 
    # to build the ReportRequest.

    reporting_service=ServiceClient(
        'ReportingService', 
        authorization_data=authorization_data, 
        environment=ENVIRONMENT,
        version=11,
    )

    # You should authenticate for Bing Ads production services with a Microsoft Account, 
    # instead of providing the Bing Ads username and password set. 
    # Authentication with a Microsoft Account is currently not supported in Sandbox.
        
    authenticate(authorization_data)
        
    main(authorization_data)

See Also

Get Started with the Bing Ads API