מבוא
במדריך הזה נסביר איך להריץ ולהוריד דוח באמצעות ה-API. הוא כולל שימוש בשאילתת דוח שמורה קיימת ויצירת שאילתת דוח אד-הוק.
דרישות מוקדמות
- גישה לרשת פעילה ב-Google Ad Manager
- ספריית לקוח של Ad Manager
Primer
אם אתם לא מכירים את הדיווח ב-Ad Manager, קראו את המאמר יצירת דוח חדש כדי לקבל סקירה כללית על הרצת דוח בממשק המשתמש של Ad Manager. בממשק המשתמש יש תצוגה מקדימה של הפלט, וגם הסברים קצרים על השילובים הנתמכים של עמודות ומאפיינים. כשיוצרים שאילתת דוח מורכבת, יכול להיות שיהיה קל יותר ליצור אותה קודם בממשק המשתמש, ואז לאחזר את השאילתה באמצעות ה-API.
אחזור של ReportQuery שמור
האובייקט ReportQuery מכיל את כל פרטי הדוח. אתם יכולים ליצור שאילתות של דוחות בממשק המשתמש של Ad Manager, ולאחזר אותן באמצעות השיטה ReportService.getSavedQueriesByStatement. מזהה השאילתה השמורה נכלל בכתובת ה-URL כשמציגים שאילתה בממשק המשתמש. לדוגמה, בכתובת ה-URL https://www.google.com/admanager/1234#reports/report/detail/report_id=456789, מזהה השאילתה הוא 456789.
אם שאילתה לא תואמת לגרסת ה-API שלכם, הערך של SavedQuery.reportQuery יהיה null והערך של SavedQuery.isCompatibleWithApiVersion יהיה false.
אפשר להריץ שאילתות שמורות תואמות עם או בלי שינויים.
Java
StatementBuilder statementBuilder = new StatementBuilder() .where("id = :id") .orderBy("id ASC") .limit(1) .withBindVariableValue("id", savedQueryId); SavedQueryPage page = reportService.getSavedQueriesByStatement(statementBuilder.toStatement()); SavedQuery savedQuery = Iterables.getOnlyElement(Arrays.asList(page.getResults())); if (!savedQuery.getIsCompatibleWithApiVersion()) { throw new IllegalStateException("The saved query is not compatible with this API version."); } ReportQuery reportQuery = savedQuery.getReportQuery();
Python
statement = (ad_manager.StatementBuilder(version='v202608') .Where('id = :id') .WithBindVariable('id', int(saved_query_id)) .Limit(1)) response = report_service.getSavedQueriesByStatement( statement.ToStatement()) if 'results' in response and len(response['results']): saved_query = response['results'][0] if saved_query['isCompatibleWithApiVersion']: report_job = {} # Set report query and optionally modify it. report_job['reportQuery'] = saved_query['reportQuery']
PHP
$statementBuilder = (new StatementBuilder())->where('id = :id') ->orderBy('id ASC') ->limit(1) ->withBindVariableValue('id', $savedQueryId); $savedQueryPage = $reportService->getSavedQueriesByStatement( $statementBuilder->toStatement() ); $savedQuery = $savedQueryPage->getResults()[0]; if ($savedQuery->getIsCompatibleWithApiVersion() === false) { throw new UnexpectedValueException( 'The saved query is not compatible with this API version.' ); } $reportQuery = $savedQuery->getReportQuery();
C#
StatementBuilder statementBuilder = new StatementBuilder() .Where("id = :id") .OrderBy("id ASC") .Limit(1) .AddValue("id", savedQueryId); SavedQueryPage page = reportService.getSavedQueriesByStatement(statementBuilder.ToStatement()); SavedQuery savedQuery = page.results[0]; if (!savedQuery.isCompatibleWithApiVersion) { throw new InvalidOperationException("Saved query is not compatible with this " + "API version"); } // Optionally modify the query. ReportQuery reportQuery = savedQuery.reportQuery;
Ruby
statement = ad_manager.new_statement_builder do |sb| sb.where = 'id = :saved_query_id' sb.with_bind_variable('saved_query_id', saved_query_id) end saved_query_page = report_service.get_saved_queries_by_statement( statement.to_statement() ) unless saved_query_page[:results].nil? saved_query = saved_query_page[:results].first if saved_query[:is_compatible_with_api_version] # Create report job. report_job = {:report_query => saved_query[:report_query]} else raise StandardError, 'Report query is not compatible with the API' end
כדי להריץ את השאילתה, עיינו בקטע יצירת ReportJob.
יצירת ReportQuery
בנוסף לשימוש בשאילתות שמורות, אתם יכולים גם ליצור ReportQuery אד הוק. כדי לעשות את זה, צריך להגדיר את המאפיינים, מאפייני המאפיינים, העמודות, המסנן וטווח התאריכים של הדוח. הדוגמה הזו היא של דוח מסירה בסיסי על הזמנה אחת.
Java
// Create report query. ReportQuery reportQuery = new ReportQuery(); reportQuery.setDimensions(new Dimension[] {Dimension.DATE, Dimension.ORDER_ID}); reportQuery.setColumns( new Column[] { Column.AD_SERVER_IMPRESSIONS, Column.AD_SERVER_CLICKS, Column.AD_SERVER_CTR, Column.AD_SERVER_CPM_AND_CPC_REVENUE }); reportQuery.setDimensionAttributes( new DimensionAttribute[] { DimensionAttribute.ORDER_TRAFFICKER, DimensionAttribute.ORDER_START_DATE_TIME, DimensionAttribute.ORDER_END_DATE_TIME }); // Create statement to filter for an order. StatementBuilder statementBuilder = new StatementBuilder() .where("ORDER_ID = :orderId") .withBindVariableValue("orderId", orderId); // Set the filter statement. reportQuery.setStatement(statementBuilder.toStatement()); // Set the start and end dates or choose a dynamic date range type. reportQuery.setDateRangeType(DateRangeType.CUSTOM_DATE); reportQuery.setStartDate( DateTimes.toDateTime("2013-05-01T00:00:00", "America/New_York").getDate()); reportQuery.setEndDate( DateTimes.toDateTime("2013-05-31T00:00:00", "America/New_York").getDate());
Python
# Create statement object to filter for an order. statement = (ad_manager.StatementBuilder(version='v202608') .Where('ORDER_ID = :id') .WithBindVariable('id', int(order_id)) .Limit(None) # No limit or offset for reports .Offset(None)) # Set the start and end dates of the report to run (past 8 days). end_date = datetime.now().date() start_date = end_date - timedelta(days=8) # Create report job. report_job = { 'reportQuery': { 'dimensions': ['ORDER_ID', 'ORDER_NAME'], 'dimensionAttributes': ['ORDER_TRAFFICKER', 'ORDER_START_DATE_TIME', 'ORDER_END_DATE_TIME'], 'statement': statement.ToStatement(), 'columns': ['AD_SERVER_IMPRESSIONS', 'AD_SERVER_CLICKS', 'AD_SERVER_CTR', 'AD_SERVER_CPM_AND_CPC_REVENUE', 'AD_SERVER_WITHOUT_CPD_AVERAGE_ECPM'], 'dateRangeType': 'CUSTOM_DATE', 'startDate': start_date, 'endDate': end_date } }
PHP
// Create report query. $reportQuery = new ReportQuery(); $reportQuery->setDimensions( [ Dimension::ORDER_ID, Dimension::ORDER_NAME ] ); $reportQuery->setDimensionAttributes( [ DimensionAttribute::ORDER_TRAFFICKER, DimensionAttribute::ORDER_START_DATE_TIME, DimensionAttribute::ORDER_END_DATE_TIME ] ); $reportQuery->setColumns( [ Column::AD_SERVER_IMPRESSIONS, Column::AD_SERVER_CLICKS, Column::AD_SERVER_CTR, Column::AD_SERVER_CPM_AND_CPC_REVENUE, Column::AD_SERVER_WITHOUT_CPD_AVERAGE_ECPM ] ); // Create statement to filter for an order. $statementBuilder = (new StatementBuilder()) ->where('ORDER_ID = :orderId') ->withBindVariableValue( 'orderId', $orderId ); // Set the filter statement. $reportQuery->setStatement($statementBuilder->toStatement()); // Set the start and end dates or choose a dynamic date range type. $reportQuery->setDateRangeType(DateRangeType::CUSTOM_DATE); $reportQuery->setStartDate( AdManagerDateTimes::fromDateTime( new DateTime( '-10 days', new DateTimeZone('America/New_York') ) ) ->getDate() ); $reportQuery->setEndDate( AdManagerDateTimes::fromDateTime( new DateTime( 'now', new DateTimeZone('America/New_York') ) ) ->getDate() );
C#
// Create report job. ReportJob reportJob = new ReportJob(); reportJob.reportQuery = new ReportQuery(); reportJob.reportQuery.dimensions = new Dimension[] { Dimension.ORDER_ID, Dimension.ORDER_NAME }; reportJob.reportQuery.dimensionAttributes = new DimensionAttribute[] { DimensionAttribute.ORDER_TRAFFICKER, DimensionAttribute.ORDER_START_DATE_TIME, DimensionAttribute.ORDER_END_DATE_TIME }; reportJob.reportQuery.columns = new Column[] { Column.AD_SERVER_IMPRESSIONS, Column.AD_SERVER_CLICKS, Column.AD_SERVER_CTR, Column.AD_SERVER_CPM_AND_CPC_REVENUE, Column.AD_SERVER_WITHOUT_CPD_AVERAGE_ECPM }; // Set a custom date range for the last 8 days reportJob.reportQuery.dateRangeType = DateRangeType.CUSTOM_DATE; System.DateTime endDateTime = System.DateTime.Now; reportJob.reportQuery.startDate = DateTimeUtilities .FromDateTime(endDateTime.AddDays(-8), "America/New_York").date; reportJob.reportQuery.endDate = DateTimeUtilities .FromDateTime(endDateTime, "America/New_York").date; // Create statement object to filter for an order. StatementBuilder statementBuilder = new StatementBuilder().Where("ORDER_ID = :id") .AddValue("id", orderId); reportJob.reportQuery.statement = statementBuilder.ToStatement();
Ruby
# Specify a report to run for the last 7 days. report_end_date = ad_manager.today() report_start_date = report_end_date - 7 # Create statement object to filter for an order. statement = ad_manager.new_report_statement_builder do |sb| sb.where = 'ORDER_ID = :order_id' sb.with_bind_variable('order_id', order_id) end # Create report query. report_query = { :date_range_type => 'CUSTOM_DATE', :start_date => report_start_date.to_h, :end_date => report_end_date.to_h, :dimensions => ['ORDER_ID', 'ORDER_NAME'], :dimension_attributes => ['ORDER_TRAFFICKER', 'ORDER_START_DATE_TIME', 'ORDER_END_DATE_TIME'], :columns => ['AD_SERVER_IMPRESSIONS', 'AD_SERVER_CLICKS', 'AD_SERVER_CTR', 'AD_SERVER_CPM_AND_CPC_REVENUE', 'AD_SERVER_WITHOUT_CPD_AVERAGE_ECPM'], :statement => statement.to_statement() }
יצירת ReportJob
אחרי שיוצרים ReportQuery, אפשר להריץ את הדוח. האובייקט ReportJob מכיל את הסטטוס של הדוח, ומאפשר לכם לדעת מתי הוא מוכן להורדה. כדי להתחיל להריץ את הדוח, משתמשים ב-method ReportService.runReportJob.
Java
// Create report job. ReportJob reportJob = new ReportJob(); reportJob.setReportQuery(reportQuery); // Run report job. reportJob = reportService.runReportJob(reportJob);
Python
# Initialize a DataDownloader. report_downloader = client.GetDataDownloader(version='v202608') try: # Run the report and wait for it to finish. report_job_id = report_downloader.WaitForReport(report_job) except errors.AdManagerReportError as e: print('Failed to generate report. Error was: %s' % e)
PHP
// Create report job and start it. $reportJob = new ReportJob(); $reportJob->setReportQuery($reportQuery); $reportJob = $reportService->runReportJob($reportJob);
C#
// Run report job. reportJob = reportService.runReportJob(reportJob);
Ruby
# Create report job. report_job = {:report_query => report_query} # Run report job. report_job = report_service.run_report_job(report_job);
הורדת הדוח
אחרי שתתחילו את משימת הדוח, יהיה לה מזהה שמוגדר על ידי השרת. כדי לבדוק את סטטוס הדוח, משתמשים במזהה הזה עם השיטה ReportService.getReportJobStatus. כשהסטטוס הוא ReportJobStatus.COMPLETED, הדוח מוכן להורדה.
בחלק מספריות הלקוח שלנו יש כלי עזר שיבצעו דגימה של ה-API וימתינו עד שהדוח יהיה מוכן. כשהדוח מוכן, אפשר לקבל את כתובת ה-URL להורדה באמצעות השיטה ReportService.getReportDownloadURL. אפשר להוריד דוח בפורמטים שונים. אם אתם רוצים לבצע עיבוד מכונה נוסף של הדוח, כדאי להשתמש בפורמט CSV_DUMP.
Java
// Create report downloader. ReportDownloader reportDownloader = new ReportDownloader(reportService, reportJob.getId()); // Wait for the report to be ready. if (reportDownloader.waitForReportReady()) { // Change to your file location. File file = File.createTempFile("delivery-report-", ".csv.gz"); System.out.printf("Downloading report to %s ...", file.toString()); // Download the report. ReportDownloadOptions options = new ReportDownloadOptions(); options.setExportFormat(ExportFormat.CSV_DUMP); options.setUseGzipCompression(true); URL url = reportDownloader.getDownloadUrl(options); Resources.asByteSource(url).copyTo(Files.asByteSink(file)); System.out.println("done."); } else { System.out.printf("Report job %d failed.%n", reportJob.getId()); }
Python
# Change to your preferred export format. export_format = 'CSV_DUMP' report_file = tempfile.NamedTemporaryFile(suffix='.csv.gz', delete=False) # Download report data. report_downloader.DownloadReportToFile( report_job_id, export_format, report_file) report_file.close() # Display results. print('Report job with id "%s" downloaded to:\n%s' % ( report_job_id, report_file.name))
PHP
// Create report downloader to poll report's status and download when // ready. $reportDownloader = new ReportDownloader( $reportService, $reportJob->getId() ); if ($reportDownloader->waitForReportToFinish()) { // Write to system temp directory by default. $filePath = sprintf( '%s.csv.gz', tempnam(sys_get_temp_dir(), 'delivery-report-') ); printf("Downloading report to %s ...%s", $filePath, PHP_EOL); // Download the report. $reportDownloader->downloadReport( ExportFormat::CSV_DUMP, $filePath ); print "done.\n"; } else { print "Report failed.\n"; }
C#
ReportUtilities reportUtilities = new ReportUtilities(reportService, reportJob.id); // Set download options. ReportDownloadOptions options = new ReportDownloadOptions(); options.exportFormat = ExportFormat.CSV_DUMP; options.useGzipCompression = true; reportUtilities.reportDownloadOptions = options; // Download the report. using (ReportResponse reportResponse = reportUtilities.GetResponse()) { reportResponse.Save(filePath); } Console.WriteLine("Report saved to \"{0}\".", filePath);
Ruby
MAX_RETRIES.times do |retry_count| # Get the report job status. report_job_status = report_service.get_report_job_status(report_job[:id]) break unless report_job_status == 'IN_PROGRESS' puts 'Report with ID %d is still running.' % report_job[:id] sleep(RETRY_INTERVAL) end puts 'Report job with ID %d finished with status "%s".' % [report_job[:id], report_service.get_report_job_status(report_job[:id])] # Get the report URL. download_url = report_service.get_report_download_url( report_job_id, export_format ) puts 'Downloading "%s" to "%s"...' % [download_url, file_name] open(file_name, 'wb') do |local_file| local_file << URI.open(download_url).read() end
קריאת נתוני הדוח
הרבה מספריות הלקוח שלנו כוללות כלי שירות לקריאת נתוני דוחות. האפשרות הזו שימושית אם רוצים לעבד את נתוני הדוח או לשלב דוחות מטווחים שונים של תאריכים. שימו לב שבקוד לדוגמה מניחים שהקובץ לא דחוס.
Java
List<String[]> rows = CsvFiles.getCsvDataArray(filePath, true); for (String[] row : rows) { // Additional row processing processReportRow(row); }
Python
with open(report_file.name, 'rb') as report: report_reader = csv.reader(report) for row in report_reader: # Additional row processing process_row(row)
PHP
$report = fopen($filePath, 'r'); while (!feof($report)) { // Additional row processing processRow(fgetcsv($report)); } fclose($report);
C#
CsvFile file = new CsvFile(); file.Read(fileName, true); for (String[] row : file.Records) { // Additional row processing ProcessReportRow(row); }
Ruby
CSV.foreach(file_name, converters: :numeric, headers: true) do |row| # Additional row processing process_row(row) end
דוגמאות נוספות לדוחות זמינות בספריות הלקוח שלנו ב-GitHub.
שאלות נפוצות
- למה כל תוצאות הדוחות ברשת הבדיקה שלי ריקות?
- ברשתות לבדיקה לא מוצגות מודעות, ולכן דוחות הצגת המודעות לא יכללו נתונים.
- למה כל תוצאות הדוחות ברשת הייצור שלי ריקות?
- יכול להיות שלמשתמש שאתם מאמתים אין גישה לנתונים שאתם מנסים לדווח עליהם. מוודאים שהרשאות התפקיד והצוותים שלהם מוגדרים בצורה נכונה.
- למה מופיעה השגיאה
ReportError.COLUMNS_NOT_SUPPORTED_FOR_REQUESTED_DIMENSIONSבדוח שלי? - לא כל השילובים של עמודות ומאפיינים נתמכים ב-Ad Manager. בדוחות מורכבים, יכול להיות שיהיה קל יותר ליצור דוח תקין בממשק המשתמש ואז לאחזר אותו באמצעות השיטה ReportService.getSavedQueriesByStatement.
- למה הדוח השמור שלי לא מוחזר ב-API?
- צריך לוודא שהבעלים של הדוח שיתף אותו עם המשתמש שאתם מאמתים.
- למה הדוח השמור שלי לא תואם ל-API?
- תכונות דיווח מסוימות לא זמינות ב-API. ההגדרה הזו כוללת עמודות, מאפיינים של מימדים, מימדים וסוגים של טווחי תאריכים. אם סוג טווח התאריכים לא תואם, אתם יכולים לשמור את הדוח עם סוג נתמך כדי שתוכלו לאחזר אותו, ואז לשנות את
ReportQueryכך שיתאים לטווח התאריכים הקבוע הרצוי. - למה מספר הקליקים או החשיפות לכל משך החיים לא תואם לדוח שלי בממשק המשתמש?
- החשיפות לאורך כל משך החיים מתייחסות לכל משך החיים של הפריט, בלי קשר לטווח התאריכים של הדוח. אם פריט עדיין מוצג, הערך כנראה ישתנה בין הפעלת שני דוחות.
- הדוחות שלי נמשכים יותר מדי זמן ולפעמים הזמן הקצוב לתפוגה שלהם נגמר. מה אפשר לעשות?
- כדי לשפר את הביצועים, אפשר לצמצם את טווח התאריכים או את מספר המאפיינים. במקום זאת, נסו להריץ כמה דוחות עם טווחי תאריכים קטנים יותר. לאחר מכן תוכלו למזג את נתוני הדוחות כדי לכסות את טווח התאריכים הרצוי.
- מה ההבדל בין העמודות
INVENTORY_LEVELו-LINE_ITEM_LEVEL? באיזה מהם כדאי להשתמש? אפשר להשתמש בעמודות עם
LINE_ITEM_LEVELרק אם ברשת שלך מופעלת הקצאה דינמית ברמת הפריט. העמודות האלה כוללות נתונים מההקצאה הדינמית ברמת הפריט ל-AdSense או ל-Ad Exchange. באופן דומה, העמודות שלINVENTORY_LEVELכוללות נתונים מהקצאה דינמית ברמת המלאי. מידע נוסף על הקצאה דינמית זמין במאמר פריטים של Ad Exchange.אם אתם עדיין לא בטוחים באילו עמודות API להשתמש, אתם יכולים ליצור שאילתה שמורה בממשק המשתמש של Ad Manager ולאחזר אותה באמצעות השיטה ReportService.getSavedQueriesByStatement.