Cum să încărcați date brute din Google Ads în Google BigQuery

Publicat: 2022-04-12

Analizând eficiența campaniilor de publicitate Google Ads în Google Analytics, este posibil să vă confruntați cu eșantionarea, agregarea datelor sau alte restricții ale interfeței sistemului. Din fericire, această problemă este ușor de rezolvat prin încărcarea datelor brute din serviciul dvs. de publicitate în Google BigQuery.

În acest articol, veți afla cum să încărcați date brute din contul dvs. Google Ads în BigQuery și să identificați toate etichetele UTM pentru campaniile etichetate automat.

Aveți nevoie de OWOX BI pentru a lega informațiile despre campanie la activitatea utilizatorilor de pe site. Înscrieți-vă pentru o demonstrație și vă vom detalia toate provocările pe care le puteți rezolva cu OWOX BI.

ÎNSCRIEȚI-VĂ PENTRU O DEMO

Cuprins

  • De ce aveți nevoie de date brute de la Google Ads
  • Două moduri de a încărca date brute din Google Ads în BigQuery
  • Cum se configurează încărcarea utilizând Transfer de date
  • Cum să configurați încărcarea utilizând Ads Script
  • Cum să conectați descărcarea de date din Google Ads la OWOX BI
  • Sfaturi utile

Aflați valoarea reală a campaniilor

Importați automat datele de cost în Google Analytics din toate serviciile dvs. de publicitate. Comparați costurile campaniei, CPC și rentabilitatea cheltuielilor publicitare într-un singur raport.

Începe procesul

De ce aveți nevoie de date brute de la Google Ads

Datele brute de la Google Ads vă vor permite să analizați campaniile de publicitate cu acuratețe până la fiecare cuvânt cheie. Încărcând date în BigQuery, puteți:

  • Creați rapoarte cât de detaliate doriți, fără a fi limitat de restricțiile GA.
  • Determinați eficacitatea campaniilor publicitare la nivel de sesiune și de utilizator.
  • Calculați ROI, ROAS, CRR în funcție de regiune, tip de utilizator (nou sau returnat), dispozitiv și orice alt parametru.
  • Gestionați-vă tarifele în mod eficient și creați liste de remarketing.
  • Combinați datele din Google Ads, Google Analytics și CRM pentru a evalua eficacitatea campaniilor pe baza marjei și valorificării articolelor dvs.
  • Antrenați-vă modelul ML pentru o planificare mai precisă.

Pentru a înțelege ce campanii, anunțuri și cuvinte cheie aduc utilizatorii pe site-ul dvs., trebuie să combinați datele din Google Ads și Analytics în BigQuery. Puteți face acest lucru utilizând fluxul OWOX BI.

Transmiterea în flux a acestor informații trimite către GBQ date neeșantionate despre comportamentul utilizatorilor de pe site-ul dvs. Hiturile sunt transmise în timp real, apoi se formează sesiuni pe baza acestor hituri.

ÎNCERCAȚI OWOX BI GRATUIT

Informațiile despre sursa de trafic OWOX BI sunt preluate din marcajul publicitar de etichete UTM. Etichetele sunt manuale și automate.

Să presupunem că ați marcat manual anunțul și ați primit această adresă URL:

https://example.com/?utm_source=facebook&utm_medium=cpc&utm_campaign=utm_tags

În acest caz, după ce vă conectați la OWOX BI, veți avea date despre sursă, canal și campanie disponibile în tabelul GBQ:

  • trafficSource.source — google
  • traficSource.medium — cpc
  • trafficSource.campaign — utm_tags

Citiți mai multe despre cum să creați corect etichetele UTM.

Dacă ați activat marcarea automată în serviciul de publicitate, fiecăruia dintre anunțurile dvs. este atribuit un parametru gclid special. Este adăugat la adresa URL a paginii de destinație atunci când utilizatorul face clic pe anunț.

Exemplu de astfel de link:

http://www.example.com/?gclid=TeSter-123

Dacă utilizați un marcaj automat, nu puteți obține sursa, mediul sau campania din gclid fără date brute - aceste câmpuri vor fi goale în tabelele BigQuery pe care le colectează OWOX BI.

Ce poți face într-un astfel de caz și cum poți obține numele campaniilor și alți parametri, având doar gclid-ul? Configurați încărcarea automată din Google Ads în GBQ.

Notă: dacă anunțul nu este marcat deloc, OWOX BI va atribui linkul după cum urmează:

  • pentru surse non-Google ca trafic de recomandare (de exemplu, facebook/recomandări)
  • pentru sursa Google ca trafic direct (direct/niciunul)

Dacă în rapoartele dvs. există mult trafic direct/niciun trafic, este posibil să nu aveți activată filtrarea bot sau să aveți un număr mare de anunțuri neetichetate.

Două moduri de a încărca date brute din Google Ads în BigQuery

Folosim și recomandăm două metode pentru a încărca date brute din Google Ads: Data Transfer Connector și Ads Script.

Modul în care alegi depinde de obiectivele și bugetul tău.

Caracteristici de transfer de date

  • Integrare nativă cu GBQ.
  • Descărcați datele istorice pentru orice perioadă fără restricții.
  • Gratuit.

Funcții Google Ads Script

  • Liber.
  • Nu puteți încărca date istorice. Sunt descărcate doar informațiile din ziua precedentă.
  • Necesită mai mult dacă doriți să configurați încărcarea dintr-un număr mare de conturi. Va trebui să faceți manual modificări de script pentru fiecare cont. În același timp, există un risc mare de a face o greșeală.

Ce ai nevoie pentru setari

Proiecte și conturi active în:

  • Google Cloud Platform (GCP)
  • Google BigQuery (GBQ)
  • OWOX BI
  • Google Ads

Acces:

  • Proprietar în GCP
  • Administrator în GBQ
  • Editare în OWOX BI. Important: numai utilizatorul care a creat canalul de streaming Google Analytics → Google BigQuery poate activa descărcarea din Google Ads.
  • Citirea în Google Ads

Cum se acordă drepturi de acces în GBQ

Deschideți consola GCP și selectați IAM și admin — Gestionați resursele din meniul lateral. Apoi selectați proiectul și faceți clic pe Adăugare membru. Introduceți adresa de e-mail a utilizatorului, selectați rolul de administrator BigQuery și salvați modificările.

Acces BigQuery

Cum se configurează încărcarea utilizând Transfer de date

Pasul 1. Creați un proiect în Google Cloud Platform

Dacă aveți deja un proiect în GCP, săriți peste acest pas. Dacă nu, deschideți consola GCP și selectați IAM și admin — Gestionați resurse din meniul lateral. Faceți clic pe butonul Creare proiect. Apoi introduceți numele proiectului, specificați organizația și faceți clic pe Creare:

Google Cloud Platform - configurarea unui proiect

Asigurați-vă că activați facturarea. Pentru a face acest lucru, deschideți fila Facturare — Gestionare cont din meniul lateral, selectați proiectul și conectați Contul de facturare:

Facturare în Google Cloud Platform

Apoi, completați toate câmpurile introducând contactele și detaliile cardului de plată. Dacă acesta este primul tău proiect în GCP, vei primi 300 USD care pot fi utilizați timp de 12 luni. Proiectele care au 1-2 conturi Google Ads și până la 100.000 de utilizatori unici pe lună vor avea suficient pentru un an. Când epuizați această limită, nu trebuie să returnați banii. Pentru utilizare ulterioară, trebuie doar să reîncărcați soldul de pe cardul pe care l-ați conectat la proiect.

Pasul 2. Activați API BigQuery

După ce creați un proiect, trebuie să activați API-ul BigQuery. Pentru a face acest lucru, accesați API-uri și servicii — Tabloul de bord din meniul lateral GCP, selectați proiectul și faceți clic pe Activare API-uri și servicii:

Activarea API BigQuery

În biblioteca API, căutați „API BigQuery” și faceți clic pe Activare:

activați API BigQuery

Pentru a utiliza API-ul, faceți clic pe Creare acreditări:

Creați acreditări

Din lista derulantă, alegeți API-ul BigQuery și faceți clic pe Ce acreditări am nevoie?

Alegerea acreditărilor

Creați numele contului de serviciu și specificați nivelul de acces BigQuery Role. Selectați tipul de cheie JSON și faceți clic pe Continuare:

Specificați acreditările

Pasul 3. Activați Data Transfer API

Apoi, trebuie să activați serviciul de date în BigQuery. Pentru a face acest lucru, deschideți GBQ și selectați Transferuri din meniul lateral din stânga. Apoi activați API-ul BigQuery Data Transfer:

activați API-ul BigQuery Data Transfer

Pasul 4. Pregătiți setul de date în GBQ

În BigQuery, selectați proiectul și faceți clic pe butonul Creare set de date din dreapta. Completați toate câmpurile obligatorii pentru noul set de date (nume, locație, păstrare):

creați setul de date în GBQ

Pasul 5. Configurați transferul de date din Google Ads

Faceți clic pe fila Transferuri din meniul lateral, apoi faceți clic pe Creare transfer. Apoi selectați Google Ads (fost AdWords) pentru sursă și introduceți numele încărcării, de exemplu, Transfer de date.

În Opțiuni de programare, puteți lăsa setarea implicită la Începe acum sau puteți seta data și ora la care doriți să începeți descărcarea. În câmpul Repetări, selectați cât de des să încărcați: zilnic, săptămânal, lunar la cerere etc.

Setări de transfer de date

Apoi, trebuie să specificați setul de date GBQ în care să încărcați rapoartele din Google Ads. Introduceți ID-ul de client (acesta este ID-ul contului dvs. Google Ads sau ID-ul MCC) și faceți clic pe Adăugați. Puteți vedea ID-ul de client în contul dvs. Google Ads în colțul din dreapta sus, lângă e-mail.

Specificați setările de transfer de date

Apoi, trebuie să autorizați contul Gmail pe care îl utilizați. În ziua următoare, informațiile vor apărea în setul de date pe care l-ați specificat când ați configurat transferul.

Drept urmare, veți primi o cantitate mare de date brute în GBQ cu care puteți lucra: tabele după campanii, segmente de public, tabele comune (personalizate), cuvinte cheie și conversii. De exemplu, dacă doriți să creați un tablou de bord personalizat, puteți extrage date neagregate din aceste tabele.

Cum să configurați încărcarea utilizând Ads Script

Deschideți contul Google Ads, faceți clic pe Instrumente și setări în colțul din dreapta sus, selectați Acțiuni în bloc — Scripturi și faceți clic pe simbolul Plus:

Script în Google Ads

Apoi, în colțul din dreapta sus, dați clic pe butonul API-uri avansate, selectați BigQuery și salvați modificările:

Salvarea modificărilor

Asigurați-vă că vă înscrieți cu contul cu care v-ați conectat la Google Ads:

Autorizare Google Ads

Copiați scriptul de mai jos. În liniile BIGQUERY_PROJECT_ID, BIGQUERY_DATASET_ID și E-mailul dvs., înlocuiți valorile cu propriile informații: numele proiectului, setul de date GBQ și e-mailul. Lipiți textul scriptului în editorul de text.

    /** * @name Export Data to BigQuery * * @overview The Export Data to BigQuery script sets up a BigQuery * dataset and tables, downloads a report from AdWords and then * loads the report to BigQuery. * * @author AdWords Scripts Team [[email protected]] * * @version 1.3 */ var CONFIG = { BIGQUERY_PROJECT_ID: 'BQ project name', BIGQUERY_DATASET_ID: AdWordsApp.currentAccount().getCustomerId().replace(/-/g, '_'), // Truncate existing data, otherwise will append. TRUNCATE_EXISTING_DATASET: false, TRUNCATE_EXISTING_TABLES: true, // Lists of reports and fields to retrieve from AdWords. REPORTS: [], RECIPIENT_EMAILS: [ 'Your email' ] }; var report = { NAME: 'CLICK_PERFORMANCE_REPORT', //https://developers.google.com/adwords/api/docs/appendix/reports/click-performance-report CONDITIONS: '', FIELDS: {'AccountDescriptiveName': 'STRING', 'AdFormat': 'STRING', 'AdGroupId': 'STRING', 'AdGroupName': 'STRING', 'AoiCountryCriteriaId': 'STRING', 'CampaignId': 'STRING', 'CampaignLocationTargetId': 'STRING', 'CampaignName': 'STRING', 'CampaignStatus': 'STRING', 'Clicks': 'INTEGER', 'ClickType': 'STRING', 'CreativeId': 'STRING', 'CriteriaId': 'STRING', 'CriteriaParameters': 'STRING', 'Date': 'DATE', 'Device': 'STRING', 'ExternalCustomerId': 'STRING', 'GclId': 'STRING', 'KeywordMatchType': 'STRING', 'LopCountryCriteriaId': 'STRING', 'Page': 'INTEGER' }, DATE_RANGE: new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, "")+','+new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, ""), DATE: new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, "") }; //Regular export CONFIG.REPORTS.push(JSON.parse(JSON.stringify(report))); //One-time historical export //for(var i=2;i<91;i++){ // report.DATE_RANGE = new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, "")+','+new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, ""); // report.DATE = new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, ""); // CONFIG.REPORTS.push(JSON.parse(JSON.stringify(report))); //} /** * Main method */ function main() { createDataset(); for (var i = 0; i < CONFIG.REPORTS.length; i++) { var reportConfig = CONFIG.REPORTS[i]; createTable(reportConfig); } var jobIds = processReports(); waitTillJobsComplete(jobIds); sendEmail(jobIds); } /** * Creates a new dataset. * * If a dataset with the same id already exists and the truncate flag * is set, will truncate the old dataset. If the truncate flag is not * set, then will not create a new dataset. */ function createDataset() { if (datasetExists()) { if (CONFIG.TRUNCATE_EXISTING_DATASET) { BigQuery.Datasets.remove(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID, {'deleteContents' : true}); Logger.log('Truncated dataset.'); } else { Logger.log('Dataset %s already exists. Will not recreate.', CONFIG.BIGQUERY_DATASET_ID); return; } } // Create new dataset. var dataSet = BigQuery.newDataset(); dataSet.friendlyName = CONFIG.BIGQUERY_DATASET_ID; dataSet.datasetReference = BigQuery.newDatasetReference(); dataSet.datasetReference.projectId = CONFIG.BIGQUERY_PROJECT_ID; dataSet.datasetReference.datasetId = CONFIG.BIGQUERY_DATASET_ID; dataSet = BigQuery.Datasets.insert(dataSet, CONFIG.BIGQUERY_PROJECT_ID); Logger.log('Created dataset with id %s.', dataSet.id); } /** * Checks if dataset already exists in project. * * @return {boolean} Returns true if dataset already exists. */ function datasetExists() { // Get a list of all datasets in project. var datasets = BigQuery.Datasets.list(CONFIG.BIGQUERY_PROJECT_ID); var datasetExists = false; // Iterate through each dataset and check for an id match. if (datasets.datasets != null) { for (var i = 0; i < datasets.datasets.length; i++) { var dataset = datasets.datasets[i]; if (dataset.datasetReference.datasetId == CONFIG.BIGQUERY_DATASET_ID) { datasetExists = true; break; } } } return datasetExists; } /** * Creates a new table. * * If a table with the same id already exists and the truncate flag * is set, will truncate the old table. If the truncate flag is not * set, then will not create a new table. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. */ function createTable(reportConfig) { var tableName = reportConfig.NAME+reportConfig.DATE; if (tableExists(tableName)) { if (CONFIG.TRUNCATE_EXISTING_TABLES) { BigQuery.Tables.remove(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID, tableName); Logger.log('Truncated table %s.', tableName); } else { Logger.log('Table %s already exists. Will not recreate.', tableName); return; } } // Create new table. var table = BigQuery.newTable(); var schema = BigQuery.newTableSchema(); var bigQueryFields = []; // Add each field to table schema. var fieldNames = Object.keys(reportConfig.FIELDS); for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i]; var bigQueryFieldSchema = BigQuery.newTableFieldSchema(); bigQueryFieldSchema.description = fieldName; bigQueryFieldSchema.name = fieldName; bigQueryFieldSchema.type = reportConfig.FIELDS[fieldName]; bigQueryFields.push(bigQueryFieldSchema); } schema.fields = bigQueryFields; table.schema = schema; table.friendlyName = tableName; table.tableReference = BigQuery.newTableReference(); table.tableReference.datasetId = CONFIG.BIGQUERY_DATASET_ID; table.tableReference.projectId = CONFIG.BIGQUERY_PROJECT_ID; table.tableReference.tableId = tableName; table = BigQuery.Tables.insert(table, CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID); Logger.log('Created table with id %s.', table.id); } /** * Checks if table already exists in dataset. * * @param {string} tableId The table id to check existence. * * @return {boolean} Returns true if table already exists. */ function tableExists(tableId) { // Get a list of all tables in the dataset. var tables = BigQuery.Tables.list(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID); var tableExists = false; // Iterate through each table and check for an id match. if (tables.tables != null) { for (var i = 0; i < tables.tables.length; i++) { var table = tables.tables[i]; if (table.tableReference.tableId == tableId) { tableExists = true; break; } } } return tableExists; } /** * Process all configured reports * * Iterates through each report to: retrieve AdWords data, * backup data to Drive (if configured), load data to BigQuery. * * @return {Array.<string>} jobIds The list of all job ids. */ function processReports() { var jobIds = []; // Iterate over each report type. for (var i = 0; i < CONFIG.REPORTS.length; i++) { var reportConfig = CONFIG.REPORTS[i]; Logger.log('Running report %s', reportConfig.NAME); // Get data as csv var csvData = retrieveAdwordsReport(reportConfig); //Logger.log(csvData); // Convert to Blob format. var blobData = Utilities.newBlob(csvData, 'application/octet-stream'); // Load data var jobId = loadDataToBigquery(reportConfig, blobData); jobIds.push(jobId); } return jobIds; } /** * Retrieves AdWords data as csv and formats any fields * to BigQuery expected format. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. * * @return {string} csvData Report in csv format. */ function retrieveAdwordsReport(reportConfig) { var fieldNames = Object.keys(reportConfig.FIELDS); var query = 'SELECT ' + fieldNames.join(', ') + ' FROM ' + reportConfig.NAME + '' + reportConfig.CONDITIONS + ' DURING ' + reportConfig.DATE_RANGE; Logger.log(query); var report = AdWordsApp.report(query); var rows = report.rows(); var csvRows = []; // Header row csvRows.push(fieldNames.join(',')); // Iterate over each row. while (rows.hasNext()) { var row = rows.next(); var csvRow = []; for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i]; var fieldValue = row[fieldName].toString(); var fieldType = reportConfig.FIELDS[fieldName]; // Strip off % and perform any other formatting here. if (fieldType == 'FLOAT' || fieldType == 'INTEGER') { if (fieldValue.charAt(fieldValue.length - 1) == '%') { fieldValue = fieldValue.substring(0, fieldValue.length - 1); } fieldValue = fieldValue.replace(/,/g,''); if (fieldValue == '--' || fieldValue == 'Unspecified') { fieldValue = '' } } // Add double quotes to any string values. if (fieldType == 'STRING') { if (fieldValue == '--') { fieldValue = '' } fieldValue = fieldValue.replace(/"/g, '""'); fieldValue = '"' + fieldValue + '"' } csvRow.push(fieldValue); } csvRows.push(csvRow.join(',')); } Logger.log('Downloaded ' + reportConfig.NAME + ' with ' + csvRows.length + ' rows.'); return csvRows.join('\n'); } /** * Creates a BigQuery insertJob to load csv data. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. * @param {Blob} data Csv report data as an 'application/octet-stream' blob. * * @return {string} jobId The job id for upload. */ function loadDataToBigquery(reportConfig, data) { // Create the data upload job. var job = { configuration: { load: { destinationTable: { projectId: CONFIG.BIGQUERY_PROJECT_ID, datasetId: CONFIG.BIGQUERY_DATASET_ID, tableId: reportConfig.NAME + reportConfig.DATE }, skipLeadingRows: 1 } } }; var insertJob = BigQuery.Jobs.insert(job, CONFIG.BIGQUERY_PROJECT_ID, data); Logger.log('Load job started for %s. Check on the status of it here: ' + 'https://bigquery.cloud.google.com/jobs/%s', reportConfig.NAME, CONFIG.BIGQUERY_PROJECT_ID); return insertJob.jobReference.jobId; } /** * Polls until all jobs are 'DONE'. * * @param {Array.<string>} jobIds The list of all job ids. */ function waitTillJobsComplete(jobIds) { var complete = false; var remainingJobs = jobIds; while (!complete) { if (AdWordsApp.getExecutionInfo().getRemainingTime() < 5){ Logger.log('Script is about to timeout, jobs ' + remainingJobs.join(',') + ' are still incomplete.'); } remainingJobs = getIncompleteJobs(remainingJobs); if (remainingJobs.length == 0) { complete = true; } if (!complete) { Logger.log(remainingJobs.length + ' jobs still being processed.'); // Wait 5 seconds before checking status again. Utilities.sleep(5000); } } Logger.log('All jobs processed.'); } /** * Iterates through jobs and returns the ids for those jobs * that are not 'DONE'. * * @param {Array.<string>} jobIds The list of job ids. * * @return {Array.<string>} remainingJobIds The list of remaining job ids. */ function getIncompleteJobs(jobIds) { var remainingJobIds = []; for (var i = 0; i < jobIds.length; i++) { var jobId = jobIds[i]; var getJob = BigQuery.Jobs.get(CONFIG.BIGQUERY_PROJECT_ID, jobId); if (getJob.status.state != 'DONE') { remainingJobIds.push(jobId); } } return remainingJobIds; } /** * Sends a notification email that jobs have completed loading. * * @param {Array.<string>} jobIds The list of all job ids. */ function sendEmail(jobIds) { var html = []; html.push( '<html>', '<body>', '<table width=800 cellpadding=0 border=0 cellspacing=0>', '<tr>', '<td colspan=2 align=right>', "<div style='font: italic normal 10pt Times New Roman, serif; " + "margin: 0; color: #666; padding-right: 5px;'>" + 'Powered by AdWords Scripts</div>', '</td>', '</tr>', "<tr bgcolor='#3c78d8'>", '<td width=500>', "<div style='font: normal 18pt verdana, sans-serif; " + "padding: 3px 10px; color: white'>Adwords data load to " + "Bigquery report</div>", '</td>', '<td align=right>', "<div style='font: normal 18pt verdana, sans-serif; " + "padding: 3px 10px; color: white'>", AdWordsApp.currentAccount().getCustomerId(), '</tr>', '</table>', '<table width=800 cellpadding=0 border=1 cellspacing=0>', "<tr bgcolor='#ddd'>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5px 5px; background-color: #ddd; ' + "text-align: left'>Report</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5px 5px; background-color: #ddd; ' + "text-align: left'>JobId</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>Rows</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>State</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>ErrorResult</td>", '</tr>', createTableRows(jobIds), '</table>', '</body>', '</html>'); MailApp.sendEmail(CONFIG.RECIPIENT_EMAILS.join(','), 'Adwords data load to Bigquery Complete', '', {htmlBody: html.join('\n')}); } /** * Creates table rows for email report. * * @param {Array.<string>} jobIds The list of all job ids. */ function createTableRows(jobIds) { var html = []; for (var i = 0; i < jobIds.length; i++) { var jobId = jobIds[i]; var job = BigQuery.Jobs.get(CONFIG.BIGQUERY_PROJECT_ID, jobId); var errorResult = '' if (job.status.errorResult) { errorResult = job.status.errorResult; } html.push('<tr>', "<td style='padding: 0px 10px'>" + job.configuration.load.destinationTable.tableId + '</td>', "<td style='padding: 0px 10px'>" + jobId + '</td>', "<td style='padding: 0px 10px'>" + job.statistics.load?job.statistics.load.outputRows:0 + '</td>', "<td style='padding: 0px 10px'>" + job.status.state + '</td>', "<td style='padding: 0px 10px'>" + errorResult + '</td>', '</tr>'); } return html.join('\n'); }
/** * @name Export Data to BigQuery * * @overview The Export Data to BigQuery script sets up a BigQuery * dataset and tables, downloads a report from AdWords and then * loads the report to BigQuery. * * @author AdWords Scripts Team [[email protected]] * * @version 1.3 */ var CONFIG = { BIGQUERY_PROJECT_ID: 'BQ project name', BIGQUERY_DATASET_ID: AdWordsApp.currentAccount().getCustomerId().replace(/-/g, '_'), // Truncate existing data, otherwise will append. TRUNCATE_EXISTING_DATASET: false, TRUNCATE_EXISTING_TABLES: true, // Lists of reports and fields to retrieve from AdWords. REPORTS: [], RECIPIENT_EMAILS: [ 'Your email' ] }; var report = { NAME: 'CLICK_PERFORMANCE_REPORT', //https://developers.google.com/adwords/api/docs/appendix/reports/click-performance-report CONDITIONS: '', FIELDS: {'AccountDescriptiveName': 'STRING', 'AdFormat': 'STRING', 'AdGroupId': 'STRING', 'AdGroupName': 'STRING', 'AoiCountryCriteriaId': 'STRING', 'CampaignId': 'STRING', 'CampaignLocationTargetId': 'STRING', 'CampaignName': 'STRING', 'CampaignStatus': 'STRING', 'Clicks': 'INTEGER', 'ClickType': 'STRING', 'CreativeId': 'STRING', 'CriteriaId': 'STRING', 'CriteriaParameters': 'STRING', 'Date': 'DATE', 'Device': 'STRING', 'ExternalCustomerId': 'STRING', 'GclId': 'STRING', 'KeywordMatchType': 'STRING', 'LopCountryCriteriaId': 'STRING', 'Page': 'INTEGER' }, DATE_RANGE: new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, "")+','+new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, ""), DATE: new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, "") }; //Regular export CONFIG.REPORTS.push(JSON.parse(JSON.stringify(report))); //One-time historical export //for(var i=2;i<91;i++){ // report.DATE_RANGE = new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, "")+','+new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, ""); // report.DATE = new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, ""); // CONFIG.REPORTS.push(JSON.parse(JSON.stringify(report))); //} /** * Main method */ function main() { createDataset(); for (var i = 0; i < CONFIG.REPORTS.length; i++) { var reportConfig = CONFIG.REPORTS[i]; createTable(reportConfig); } var jobIds = processReports(); waitTillJobsComplete(jobIds); sendEmail(jobIds); } /** * Creates a new dataset. * * If a dataset with the same id already exists and the truncate flag * is set, will truncate the old dataset. If the truncate flag is not * set, then will not create a new dataset. */ function createDataset() { if (datasetExists()) { if (CONFIG.TRUNCATE_EXISTING_DATASET) { BigQuery.Datasets.remove(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID, {'deleteContents' : true}); Logger.log('Truncated dataset.'); } else { Logger.log('Dataset %s already exists. Will not recreate.', CONFIG.BIGQUERY_DATASET_ID); return; } } // Create new dataset. var dataSet = BigQuery.newDataset(); dataSet.friendlyName = CONFIG.BIGQUERY_DATASET_ID; dataSet.datasetReference = BigQuery.newDatasetReference(); dataSet.datasetReference.projectId = CONFIG.BIGQUERY_PROJECT_ID; dataSet.datasetReference.datasetId = CONFIG.BIGQUERY_DATASET_ID; dataSet = BigQuery.Datasets.insert(dataSet, CONFIG.BIGQUERY_PROJECT_ID); Logger.log('Created dataset with id %s.', dataSet.id); } /** * Checks if dataset already exists in project. * * @return {boolean} Returns true if dataset already exists. */ function datasetExists() { // Get a list of all datasets in project. var datasets = BigQuery.Datasets.list(CONFIG.BIGQUERY_PROJECT_ID); var datasetExists = false; // Iterate through each dataset and check for an id match. if (datasets.datasets != null) { for (var i = 0; i < datasets.datasets.length; i++) { var dataset = datasets.datasets[i]; if (dataset.datasetReference.datasetId == CONFIG.BIGQUERY_DATASET_ID) { datasetExists = true; break; } } } return datasetExists; } /** * Creates a new table. * * If a table with the same id already exists and the truncate flag * is set, will truncate the old table. If the truncate flag is not * set, then will not create a new table. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. */ function createTable(reportConfig) { var tableName = reportConfig.NAME+reportConfig.DATE; if (tableExists(tableName)) { if (CONFIG.TRUNCATE_EXISTING_TABLES) { BigQuery.Tables.remove(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID, tableName); Logger.log('Truncated table %s.', tableName); } else { Logger.log('Table %s already exists. Will not recreate.', tableName); return; } } // Create new table. var table = BigQuery.newTable(); var schema = BigQuery.newTableSchema(); var bigQueryFields = []; // Add each field to table schema. var fieldNames = Object.keys(reportConfig.FIELDS); for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i]; var bigQueryFieldSchema = BigQuery.newTableFieldSchema(); bigQueryFieldSchema.description = fieldName; bigQueryFieldSchema.name = fieldName; bigQueryFieldSchema.type = reportConfig.FIELDS[fieldName]; bigQueryFields.push(bigQueryFieldSchema); } schema.fields = bigQueryFields; table.schema = schema; table.friendlyName = tableName; table.tableReference = BigQuery.newTableReference(); table.tableReference.datasetId = CONFIG.BIGQUERY_DATASET_ID; table.tableReference.projectId = CONFIG.BIGQUERY_PROJECT_ID; table.tableReference.tableId = tableName; table = BigQuery.Tables.insert(table, CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID); Logger.log('Created table with id %s.', table.id); } /** * Checks if table already exists in dataset. * * @param {string} tableId The table id to check existence. * * @return {boolean} Returns true if table already exists. */ function tableExists(tableId) { // Get a list of all tables in the dataset. var tables = BigQuery.Tables.list(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID); var tableExists = false; // Iterate through each table and check for an id match. if (tables.tables != null) { for (var i = 0; i < tables.tables.length; i++) { var table = tables.tables[i]; if (table.tableReference.tableId == tableId) { tableExists = true; break; } } } return tableExists; } /** * Process all configured reports * * Iterates through each report to: retrieve AdWords data, * backup data to Drive (if configured), load data to BigQuery. * * @return {Array.<string>} jobIds The list of all job ids. */ function processReports() { var jobIds = []; // Iterate over each report type. for (var i = 0; i < CONFIG.REPORTS.length; i++) { var reportConfig = CONFIG.REPORTS[i]; Logger.log('Running report %s', reportConfig.NAME); // Get data as csv var csvData = retrieveAdwordsReport(reportConfig); //Logger.log(csvData); // Convert to Blob format. var blobData = Utilities.newBlob(csvData, 'application/octet-stream'); // Load data var jobId = loadDataToBigquery(reportConfig, blobData); jobIds.push(jobId); } return jobIds; } /** * Retrieves AdWords data as csv and formats any fields * to BigQuery expected format. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. * * @return {string} csvData Report in csv format. */ function retrieveAdwordsReport(reportConfig) { var fieldNames = Object.keys(reportConfig.FIELDS); var query = 'SELECT ' + fieldNames.join(', ') + ' FROM ' + reportConfig.NAME + '' + reportConfig.CONDITIONS + ' DURING ' + reportConfig.DATE_RANGE; Logger.log(query); var report = AdWordsApp.report(query); var rows = report.rows(); var csvRows = []; // Header row csvRows.push(fieldNames.join(',')); // Iterate over each row. while (rows.hasNext()) { var row = rows.next(); var csvRow = []; for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i]; var fieldValue = row[fieldName].toString(); var fieldType = reportConfig.FIELDS[fieldName]; // Strip off % and perform any other formatting here. if (fieldType == 'FLOAT' || fieldType == 'INTEGER') { if (fieldValue.charAt(fieldValue.length - 1) == '%') { fieldValue = fieldValue.substring(0, fieldValue.length - 1); } fieldValue = fieldValue.replace(/,/g,''); if (fieldValue == '--' || fieldValue == 'Unspecified') { fieldValue = '' } } // Add double quotes to any string values. if (fieldType == 'STRING') { if (fieldValue == '--') { fieldValue = '' } fieldValue = fieldValue.replace(/"/g, '""'); fieldValue = '"' + fieldValue + '"' } csvRow.push(fieldValue); } csvRows.push(csvRow.join(',')); } Logger.log('Downloaded ' + reportConfig.NAME + ' with ' + csvRows.length + ' rows.'); return csvRows.join('\n'); } /** * Creates a BigQuery insertJob to load csv data. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. * @param {Blob} data Csv report data as an 'application/octet-stream' blob. * * @return {string} jobId The job id for upload. */ function loadDataToBigquery(reportConfig, data) { // Create the data upload job. var job = { configuration: { load: { destinationTable: { projectId: CONFIG.BIGQUERY_PROJECT_ID, datasetId: CONFIG.BIGQUERY_DATASET_ID, tableId: reportConfig.NAME + reportConfig.DATE }, skipLeadingRows: 1 } } }; var insertJob = BigQuery.Jobs.insert(job, CONFIG.BIGQUERY_PROJECT_ID, data); Logger.log('Load job started for %s. Check on the status of it here: ' + 'https://bigquery.cloud.google.com/jobs/%s', reportConfig.NAME, CONFIG.BIGQUERY_PROJECT_ID); return insertJob.jobReference.jobId; } /** * Polls until all jobs are 'DONE'. * * @param {Array.<string>} jobIds The list of all job ids. */ function waitTillJobsComplete(jobIds) { var complete = false; var remainingJobs = jobIds; while (!complete) { if (AdWordsApp.getExecutionInfo().getRemainingTime() < 5){ Logger.log('Script is about to timeout, jobs ' + remainingJobs.join(',') + ' are still incomplete.'); } remainingJobs = getIncompleteJobs(remainingJobs); if (remainingJobs.length == 0) { complete = true; } if (!complete) { Logger.log(remainingJobs.length + ' jobs still being processed.'); // Wait 5 seconds before checking status again. Utilities.sleep(5000); } } Logger.log('All jobs processed.'); } /** * Iterates through jobs and returns the ids for those jobs * that are not 'DONE'. * * @param {Array.<string>} jobIds The list of job ids. * * @return {Array.<string>} remainingJobIds The list of remaining job ids. */ function getIncompleteJobs(jobIds) { var remainingJobIds = []; for (var i = 0; i < jobIds.length; i++) { var jobId = jobIds[i]; var getJob = BigQuery.Jobs.get(CONFIG.BIGQUERY_PROJECT_ID, jobId); if (getJob.status.state != 'DONE') { remainingJobIds.push(jobId); } } return remainingJobIds; } /** * Sends a notification email that jobs have completed loading. * * @param {Array.<string>} jobIds The list of all job ids. */ function sendEmail(jobIds) { var html = []; html.push( '<html>', '<body>', '<table width=800 cellpadding=0 border=0 cellspacing=0>', '<tr>', '<td colspan=2 align=right>', "<div style='font: italic normal 10pt Times New Roman, serif; " + "margin: 0; color: #666; padding-right: 5px;'>" + 'Powered by AdWords Scripts</div>', '</td>', '</tr>', "<tr bgcolor='#3c78d8'>", '<td width=500>', "<div style='font: normal 18pt verdana, sans-serif; " + "padding: 3px 10px; color: white'>Adwords data load to " + "Bigquery report</div>", '</td>', '<td align=right>', "<div style='font: normal 18pt verdana, sans-serif; " + "padding: 3px 10px; color: white'>", AdWordsApp.currentAccount().getCustomerId(), '</tr>', '</table>', '<table width=800 cellpadding=0 border=1 cellspacing=0>', "<tr bgcolor='#ddd'>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5px 5px; background-color: #ddd; ' + "text-align: left'>Report</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5px 5px; background-color: #ddd; ' + "text-align: left'>JobId</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>Rows</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>State</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>ErrorResult</td>", '</tr>', createTableRows(jobIds), '</table>', '</body>', '</html>'); MailApp.sendEmail(CONFIG.RECIPIENT_EMAILS.join(','), 'Adwords data load to Bigquery Complete', '', {htmlBody: html.join('\n')}); } /** * Creates table rows for email report. * * @param {Array.<string>} jobIds The list of all job ids. */ function createTableRows(jobIds) { var html = []; for (var i = 0; i < jobIds.length; i++) { var jobId = jobIds[i]; var job = BigQuery.Jobs.get(CONFIG.BIGQUERY_PROJECT_ID, jobId); var errorResult = '' if (job.status.errorResult) { errorResult = job.status.errorResult; } html.push('<tr>', "<td style='padding: 0px 10px'>" + job.configuration.load.destinationTable.tableId + '</td>', "<td style='padding: 0px 10px'>" + jobId + '</td>', "<td style='padding: 0px 10px'>" + job.statistics.load?job.statistics.load.outputRows:0 + '</td>', "<td style='padding: 0px 10px'>" + job.status.state + '</td>', "<td style='padding: 0px 10px'>" + errorResult + '</td>', '</tr>'); } return html.join('\n'); }

Înainte de a rula scriptul, asigurați-vă că faceți clic pe butonul Previzualizare din colțul din dreapta jos pentru a verifica rezultatul. Dacă există erori în acesta, sistemul vă va avertiza și va indica în ce linie a avut loc, ca în această captură de ecran:

Rulați scriptul

Dacă nu există erori, faceți clic pe butonul Run:

configurați încărcarea din Google Ads

Ca urmare, veți primi un nou raport CLICK_PERFORMANCE_REPORT în GBQ-ul dvs., care va fi disponibil a doua zi:

rezultă în GBQ

Amintiți-vă că atunci când utilizați Transferul de date, obțineți o cantitate mare de date brute neagregate. Cu Ads Script, veți avea doar informații despre anumite câmpuri.

Următoarele câmpuri din această încărcare sunt incluse în tabelele OWOX BI legate de sesiune:

  • GclId
  • CampaignId
  • Numele campaniei
  • AdGroupId
  • AdGroupName
  • CriteriaId
  • CriteriaParameters
  • KeywordMatchType

Cum să conectați descărcarea de date din Google Ads la OWOX BI

Acum trebuie să combinați informațiile din Google Ads cu datele site-ului pentru a înțelege prin ce campanii au ajuns utilizatorii pe site-ul dvs. Tabelele pe care le obțineți în BigQuery, cum ar fi Transfer de date, nu au un parametru ID de client. Puteți determina care client a făcut clic pe anunțuri numai prin conectarea datelor gclid la datele fluxului OWOX BI.

Dacă nu aveți încă un canal de streaming Google Analytics → Google BigQuery în OWOX BI, citiți instrucțiunile despre cum să îl creați.

Apoi accesați proiectul dvs. OWOX BI și deschideți această conductă. Faceți clic pe fila Setări, iar sub Colectarea datelor sesiunii, faceți clic pe Editați setările:

Setările conductei OWOX BI

Utilizați glisorul pentru a activa colectarea datelor pentru campaniile Google Ads etichetate automat și faceți clic pe Modificați setările:

activați colectarea datelor pentru Google Ads

Selectați tipul de marcare AutoLabel, specificați cum să încărcați scripturile Transfer de date sau Ads în BigQuery. Specificați proiectul și setul de date din care vor fi descărcate datele Google Ads și salvați setările:

Salvați setările

Sfaturi utile

Sfat 1. Cu Transferul de date, puteți încărca date istorice din Google Ads în GBQ. În același timp, nu există restricții privind perioada totală de încărcare (fie pentru un an, fie pentru trei), dar cu date pentru doar 180 de zile la un moment dat.

Puteți activa încărcarea și specifica perioada utilizând butonul Programează completarea din fila Transferuri selectând transferul dorit:

încărcați date istorice

Sfat 2. Dacă doriți să verificați numărul de conturi Google Ads pentru care GCP va taxa, trebuie să determinați numărul de ExternalCustomerID din tabelul Clienți utilizând interogarea:

    SELECT ExternalCustomerId FROM `project_name.dataset_name.Customer_*` WHERE _PARTITIONTIME >= "2020-01-01 00:00:00" AND _PARTITIONTIME < "2020-07-10 00:00:00" group by 1
SELECT ExternalCustomerId FROM `project_name.dataset_name.Customer_*` WHERE _PARTITIONTIME >= "2020-01-01 00:00:00" AND _PARTITIONTIME < "2020-07-10 00:00:00" group by 1

Puteți edita datele în interogare.

Sfat 3. Puteți accesa singur datele încărcate folosind interogări SQL. Iată, de exemplu, o interogare pentru a determina eficiența campaniilor din tabelele „Campaign” și „CampaignBasicStats” derivate din transferul de date:

    SELECT {source language="sql"} c.ExternalCustomerId, c.CampaignName, c.CampaignStatus, SUM(cs.Impressions) AS Impressions, SUM(cs.Interactions) AS Interactions, {/source} (SUM(cs.Cost) / 1000000) AS Cost FROM `[DATASET].Campaign_[CUSTOMER_ID]` c LEFT JOIN {source language="sql"} {source language="sql"} `[DATASET].CampaignBasicStats_[CUSTOMER_ID]` cs ON (c.CampaignId = cs.CampaignId AND cs._DATA_DATE BETWEEN DATE_ADD(CURRENT_DATE(), INTERVAL -31 DAY) AND DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)) WHERE c._DATA_DATE = c._LATEST_DATE GROUP BY 1, 2, 3 ORDER BY Impressions DESC
SELECT {source language="sql"} c.ExternalCustomerId, c.CampaignName, c.CampaignStatus, SUM(cs.Impressions) AS Impressions, SUM(cs.Interactions) AS Interactions, {/source} (SUM(cs.Cost) / 1000000) AS Cost FROM `[DATASET].Campaign_[CUSTOMER_ID]` c LEFT JOIN {source language="sql"} {source language="sql"} `[DATASET].CampaignBasicStats_[CUSTOMER_ID]` cs ON (c.CampaignId = cs.CampaignId AND cs._DATA_DATE BETWEEN DATE_ADD(CURRENT_DATE(), INTERVAL -31 DAY) AND DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)) WHERE c._DATA_DATE = c._LATEST_DATE GROUP BY 1, 2, 3 ORDER BY Impressions DESC

PS Dacă aveți nevoie de ajutor pentru încărcarea și îmbinarea datelor în Google BigQuery, suntem gata să vă ajutăm. Înscrieți-vă pentru o demonstrație - și vom discuta detaliile.

ÎNSCRIEȚI-VĂ PENTRU O DEMO