{"id":3811,"date":"2026-08-18T15:34:07","date_gmt":"2026-08-18T13:34:07","guid":{"rendered":"https:\/\/thedatastory.nl\/?p=3811"},"modified":"2026-08-18T15:45:22","modified_gmt":"2026-08-18T13:45:22","slug":"how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform","status":"publish","type":"post","link":"https:\/\/thedatastory.nl\/en\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/","title":{"rendered":"How to build a production-ready marketing data pipeline for Google Ads using Dataform"},"content":{"rendered":"<p class=\"wp-block-paragraph\">Now is the time to invest in a <a href=\"https:\/\/thedatastory.nl\/en\/data-stories\/why-you-need-a-marketing-data-pipeline-in-2026\/\">solid data warehouse<\/a>. As marketing data scales, querying, for instance, raw Google Ads tables directly quickly becomes expensive and inefficient. What\u2019s more, third-party ETL tools can become quite costly as data volumes scale, since many vendors charge per row synced or per active connector. Beyond costs, Google Ads data is heavily fragmented. Metrics and dimensions are split across separate raw tables, making raw analysis complex.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The solution? Shift to a ELT (Extract, Load, Transform) pipeline. Instead of paying for external connectors or settling for GA4&#8217;s pre-aggregated reports, you save raw data directly into Google BigQuery and use Dataform to model it exactly how you want.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this step-by-step guide, you\u2019ll learn how to build a scalable, automated Google Ads data pipeline using BigQuery Data Transfer Service and Dataform. While this post focuses on campaign-level data, the exact same architecture applies to ad groups, keywords, search terms, and beyond.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>The big picture: a 5-step pipeline architecture<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This pipeline follows a modular five-stage flow:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set up the Google Ads Data Transfer<\/li>\n\n\n\n<li>Initialize Dataform repository and workspace<\/li>\n\n\n\n<li>Declare sources<\/li>\n\n\n\n<li>Create model<\/li>\n\n\n\n<li>Scheduling<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Please note that this is a simplified version of a marketing data pipeline. While an enterprise setup might, for instance, include data quality assertions, this 5-step framework gives you everything you need to get a clean, automated campaign-level pipeline running in Dataform.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 1: set up the Google Ads Data Transfer via BigQuery<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">First, we need to offload Google Ads data in BigQuery. Fortunately, this is a piece of cake. The Google Ads Data Transfer automatically extracts Google Ads reports and loads them directly into BigQuery. All you need is a Google Ads Customer ID, which is usually being found at the right top corner of the Google Ads interface.<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"554\" src=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-10-1024x554.png\" alt=\"\" class=\"wp-image-3812\" srcset=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-10-1024x554.png 1024w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-10-300x162.png 300w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-10-768x415.png 768w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-10-1536x830.png 1536w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-10-18x10.png 18w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-10.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In the BigQuery menu, go to Data Transfer. There you will see the option to create a Transfer. From the dropdown menu, choose Google Ads and fill in the Customer ID. For now you can use the standard report type. I advise you to include PMAX campaigns, so the following option needs to be checked:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"128\" src=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-11-1024x128.png\" alt=\"\" class=\"wp-image-3813\" srcset=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-11-1024x128.png 1024w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-11-300x37.png 300w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-11-768x96.png 768w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-11-18x2.png 18w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-11.png 1074w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If you follow the steps, you will be prompted to create a new dataset, but keep in mind to use the same regions for all datasets. For instance if you want to join Google Ads-data and GA4-data, the datasets must be in the same region.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Before saving, you can choose the cadence of the Google Ads export. I would leave it once per 24 hours.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 2: initialize your Dataform repository<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Setting up a Dataform repository sets up the backbone of our marketing pipeline. In Dataform, a Repository acts as the central Git container for your code, while a Development Workspace acts as an isolated sandbox where you edit, compile, and test SQLX models without affecting production. If you want to know more about the advantages of Dataform, please read our blog about the <a href=\"https:\/\/thedatastory.nl\/en\/data-stories\/getting-started-with-dataform-tips-and-tricks-to-make-you-more-confident\/\">tips and tricks<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is now time to create a repository. Just make sure that you have BigQuery Admin and Dataform Admin rights. In the left menu go to Dataform and create a repository. Give the repository a name, something like \u2018marketing-pipeline-company\u2019 and pick a region. After initializing a repository, you can create a workspace:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" width=\"851\" height=\"1024\" src=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-14-851x1024.png\" alt=\"\" class=\"wp-image-3817\" style=\"aspect-ratio:0.8310609011816648;width:402px;height:auto\" srcset=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-14-851x1024.png 851w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-14-249x300.png 249w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-14-768x924.png 768w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-14-1276x1536.png 1276w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-14-10x12.png 10w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-14.png 1316w\" sizes=\"(max-width: 851px) 100vw, 851px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 3: declare source tables in Dataform<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Once the Google Ads Data Transfer has started to offload data and a Dataform repository is made, we can declare the sources. By default, Dataform does not know that tables like CampaignBasicStats (table in the Google Ads Data Transfer) exist in your raw BigQuery dataset. Declaring them explicitly informs Dataform where to find the raw inputs, allows it to track lineage, and enables you to reference these tables across all models using the <em>ref() function<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new file in your workspace and name it <em>definitions\/sources\/google_ads_sources.sqlx<\/em>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"301\" src=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-13-1-1024x301.png\" alt=\"\" class=\"wp-image-3815\" srcset=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-13-1-1024x301.png 1024w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-13-1-300x88.png 300w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-13-1-768x226.png 768w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-13-1-1536x451.png 1536w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-13-1-18x5.png 18w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-13-1.png 1538w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In the file you add the following blocks and replace the database with the name of your BigQuery project. Do the same for the schema (the name of the dataset you created in the Data Transfer) and replace the name with the exact name of the Google Ads-tables (usually CampaignBasicStats_xxxxxxxx is being used where the last part is the Customer ID). In this case we only want to declare the table with the campaign names and the table with the campaign metrics.\u00a0<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"623\" src=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-12-1024x623.png\" alt=\"\" class=\"wp-image-3816\" srcset=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-12-1024x623.png 1024w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-12-300x183.png 300w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-12-768x467.png 768w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-12-18x12.png 18w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-12.png 1160w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 4: build transformation models (SQLX)<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In Dataform, SQLX is an extension of standard SQL created specifically for data modeling. It combines BigQuery SQL with a <em>config {}<\/em> block (to define metadata, schemas, and target output types) and JavaScript expressions like <em>${ref()}<\/em> to automatically build dependencies between models.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s make three files:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>definitions\/staging\/google_ads_dim.sqlx<\/em><\/li>\n\n\n\n<li><em>definitions\/staging\/google_ads_fact.sqlx<\/em><\/li>\n\n\n\n<li><em>definitions\/mart_google_ads\/google_ads_reporting.sqlx<\/em><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In the first table we will make an overview of all the campaign names:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-15-1024x769.png\" alt=\"\" class=\"wp-image-3818\" srcset=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-15-1024x769.png 1024w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-15-300x225.png 300w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-15-768x577.png 768w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-15-16x12.png 16w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-15.png 1472w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We can do the same for the metrics table:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" src=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-18-1024x584.png\" alt=\"\" class=\"wp-image-3821\" srcset=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-18-1024x584.png 1024w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-18-300x171.png 300w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-18-768x438.png 768w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-18-1536x875.png 1536w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-18-18x10.png 18w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-18.png 1688w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Because of the declaration configuration, we can use a simple name alias to reference raw BigQuery tables using <em>${ref()}<\/em>. In addition, the <em>config {}<\/em> block is a core element of every SQLX model. It acts as the metadata of a model, including:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>type<\/em>: determines if Dataform creates a BigQuery view, table, incremental table, or assertion. For now we have opted for table, but incremental would be preferable to add data from each campaign everyday without loading the entire table everyday.<\/li>\n\n\n\n<li><em>schema<\/em>: Specifies the target BigQuery dataset.<\/li>\n\n\n\n<li><em>description<\/em>: Adds documentation directly to the BigQuery table catalog.<\/li>\n\n\n\n<li><em>tags:<\/em> For each model we can include tags so that we can easily schedule <\/li>\n\n\n\n<li><em>bigquery<\/em>: Configures performance optimizations like partitionBy and clusterBy.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Ultimately we can join these staging tables in a reporting table.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can find the queries on my Github.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 5: schedule the pipeline<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To ensure your marketing dashboards always display up-to-date data, you must automate the execution flow. Dataform has two built-in features: release configurations and workflow configurations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First of all, you need to create a release configuration. The reason for this is Dataform needs to compile the code at a specific point in time so that it can be safely run. If compilation fails because of a bad merge request, the workflow configuration will continue using the last known good compiled release.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"173\" src=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-17-1024x173.png\" alt=\"\" class=\"wp-image-3820\" srcset=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-17-1024x173.png 1024w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-17-300x51.png 300w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-17-768x129.png 768w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-17-1536x259.png 1536w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-17-18x3.png 18w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-17.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Secondly, you have to create a workflow configuration. Basically the workflow configuration actually runs the SQL code inside BigQuery. Here you can set your execution time and select all actions or tags (have you noticed I added the tag <em>\u2018ads\u2019<\/em> in the config?) you want to run. Because we use <em>${ref()}<\/em> in the models, a model will not run until all of its upstream dependencies have finished successfully.<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"925\" src=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-16-1024x925.png\" alt=\"\" class=\"wp-image-3819\" style=\"width:559px;height:auto\" srcset=\"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-16-1024x925.png 1024w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-16-300x271.png 300w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-16-768x694.png 768w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-16-13x12.png 13w, https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/unnamed-16.png 1302w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Next steps<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Building a Google Ads pipeline with BigQuery Data Transfer Service and Dataform transitions your analytics from manual, fragmented reporting to an automated workflow. But Google Ads is only one piece of the puzzle. To build a true single source of truth, here is how to expand your architecture:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Capture the entire customer journey: Bring Facebook Ads (Meta), TikTok Ads, and Klaviyo email data into BigQuery. Modern conversion paths are rarely linear as customers interact with multiple touchpoints before buying.<\/li>\n\n\n\n<li>Unify attribution with GA4: Every ad network uses its own attribution model, often taking 100% credit for the same conversion. By joining all paid media spend directly with GA4 conversion events in Dataform, you create an unbiased, single source of truth across all channels.<\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Now is the time to invest in a solid data warehouse. As marketing data scales, querying, for instance, raw Google Ads tables directly quickly becomes expensive and inefficient. What\u2019s more, [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":3824,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_tribe_ticket_capacity":"0","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[2],"tags":[],"class_list":["post-3811","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-data-stories"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>How to build a production-ready marketing data pipeline for Google Ads using Dataform - The Data Story<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/thedatastory.nl\/en\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to build a production-ready marketing data pipeline for Google Ads using Dataform - The Data Story\" \/>\n<meta property=\"og:description\" content=\"Now is the time to invest in a solid data warehouse. As marketing data scales, querying, for instance, raw Google Ads tables directly quickly becomes expensive and inefficient. What\u2019s more, [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/thedatastory.nl\/en\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/\" \/>\n<meta property=\"og:site_name\" content=\"The Data Story\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-18T13:34:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-18T13:45:22+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"1408\" \/>\n\t<meta property=\"og:image:height\" content=\"768\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jim\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jim\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/\"},\"author\":{\"name\":\"Jim\",\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/#\\\/schema\\\/person\\\/97e8de2c90c94de7c6166f2fc124f8e7\"},\"headline\":\"How to build a production-ready marketing data pipeline for Google Ads using Dataform\",\"datePublished\":\"2026-08-18T13:34:07+00:00\",\"dateModified\":\"2026-08-18T13:45:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/\"},\"wordCount\":1241,\"publisher\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/thedatastory.nl\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg\",\"articleSection\":[\"Data stories\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/\",\"url\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/\",\"name\":\"How to build a production-ready marketing data pipeline for Google Ads using Dataform - The Data Story\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/thedatastory.nl\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg\",\"datePublished\":\"2026-08-18T13:34:07+00:00\",\"dateModified\":\"2026-08-18T13:45:22+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/#primaryimage\",\"url\":\"https:\\\/\\\/thedatastory.nl\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg\",\"contentUrl\":\"https:\\\/\\\/thedatastory.nl\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg\",\"width\":1408,\"height\":768},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/data-stories\\\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Data stories\",\"item\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/data-stories\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"How to build a production-ready marketing data pipeline for Google Ads using Dataform\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/\",\"name\":\"The Data Story\",\"description\":\"Data Analyse, Visualisatie &amp; Automation\",\"publisher\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/#organization\",\"name\":\"The Data Story\",\"url\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/thedatastory.nl\\\/wp-content\\\/uploads\\\/2021\\\/11\\\/Logo-negatief.svg\",\"contentUrl\":\"https:\\\/\\\/thedatastory.nl\\\/wp-content\\\/uploads\\\/2021\\\/11\\\/Logo-negatief.svg\",\"width\":250,\"height\":49,\"caption\":\"The Data Story\"},\"image\":{\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/#\\\/schema\\\/person\\\/97e8de2c90c94de7c6166f2fc124f8e7\",\"name\":\"Jim\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a9c33a79e7cf243afe88332c81c09efefd76bf65cf4eed64db5123dc9ac7a2c8?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a9c33a79e7cf243afe88332c81c09efefd76bf65cf4eed64db5123dc9ac7a2c8?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a9c33a79e7cf243afe88332c81c09efefd76bf65cf4eed64db5123dc9ac7a2c8?s=96&d=mm&r=g\",\"caption\":\"Jim\"},\"url\":\"https:\\\/\\\/thedatastory.nl\\\/en\\\/author\\\/jim\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to build a production-ready marketing data pipeline for Google Ads using Dataform - The Data Story","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/thedatastory.nl\/en\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/","og_locale":"en_US","og_type":"article","og_title":"How to build a production-ready marketing data pipeline for Google Ads using Dataform - The Data Story","og_description":"Now is the time to invest in a solid data warehouse. As marketing data scales, querying, for instance, raw Google Ads tables directly quickly becomes expensive and inefficient. What\u2019s more, [&hellip;]","og_url":"https:\/\/thedatastory.nl\/en\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/","og_site_name":"The Data Story","article_published_time":"2026-08-18T13:34:07+00:00","article_modified_time":"2026-08-18T13:45:22+00:00","og_image":[{"width":1408,"height":768,"url":"http:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg","type":"image\/jpeg"}],"author":"Jim","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Jim","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/#article","isPartOf":{"@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/"},"author":{"name":"Jim","@id":"https:\/\/thedatastory.nl\/en\/#\/schema\/person\/97e8de2c90c94de7c6166f2fc124f8e7"},"headline":"How to build a production-ready marketing data pipeline for Google Ads using Dataform","datePublished":"2026-08-18T13:34:07+00:00","dateModified":"2026-08-18T13:45:22+00:00","mainEntityOfPage":{"@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/"},"wordCount":1241,"publisher":{"@id":"https:\/\/thedatastory.nl\/en\/#organization"},"image":{"@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/#primaryimage"},"thumbnailUrl":"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg","articleSection":["Data stories"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/","url":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/","name":"How to build a production-ready marketing data pipeline for Google Ads using Dataform - The Data Story","isPartOf":{"@id":"https:\/\/thedatastory.nl\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/#primaryimage"},"image":{"@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/#primaryimage"},"thumbnailUrl":"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg","datePublished":"2026-08-18T13:34:07+00:00","dateModified":"2026-08-18T13:45:22+00:00","breadcrumb":{"@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/#primaryimage","url":"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg","contentUrl":"https:\/\/thedatastory.nl\/wp-content\/uploads\/2026\/08\/Gemini_Generated_Image_sxstxisxstxisxst.jpeg","width":1408,"height":768},{"@type":"BreadcrumbList","@id":"https:\/\/thedatastory.nl\/data-stories\/how-to-build-a-production-ready-marketing-data-pipeline-for-google-ads-using-dataform\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/thedatastory.nl\/en\/"},{"@type":"ListItem","position":2,"name":"Data stories","item":"https:\/\/thedatastory.nl\/en\/data-stories\/"},{"@type":"ListItem","position":3,"name":"How to build a production-ready marketing data pipeline for Google Ads using Dataform"}]},{"@type":"WebSite","@id":"https:\/\/thedatastory.nl\/en\/#website","url":"https:\/\/thedatastory.nl\/en\/","name":"The Data Story","description":"Data Analyse, Visualisatie &amp; Automation","publisher":{"@id":"https:\/\/thedatastory.nl\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/thedatastory.nl\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/thedatastory.nl\/en\/#organization","name":"The Data Story","url":"https:\/\/thedatastory.nl\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/thedatastory.nl\/en\/#\/schema\/logo\/image\/","url":"https:\/\/thedatastory.nl\/wp-content\/uploads\/2021\/11\/Logo-negatief.svg","contentUrl":"https:\/\/thedatastory.nl\/wp-content\/uploads\/2021\/11\/Logo-negatief.svg","width":250,"height":49,"caption":"The Data Story"},"image":{"@id":"https:\/\/thedatastory.nl\/en\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/thedatastory.nl\/en\/#\/schema\/person\/97e8de2c90c94de7c6166f2fc124f8e7","name":"Jim","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/a9c33a79e7cf243afe88332c81c09efefd76bf65cf4eed64db5123dc9ac7a2c8?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a9c33a79e7cf243afe88332c81c09efefd76bf65cf4eed64db5123dc9ac7a2c8?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a9c33a79e7cf243afe88332c81c09efefd76bf65cf4eed64db5123dc9ac7a2c8?s=96&d=mm&r=g","caption":"Jim"},"url":"https:\/\/thedatastory.nl\/en\/author\/jim\/"}]}},"_links":{"self":[{"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/posts\/3811","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/comments?post=3811"}],"version-history":[{"count":1,"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/posts\/3811\/revisions"}],"predecessor-version":[{"id":3822,"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/posts\/3811\/revisions\/3822"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/media\/3824"}],"wp:attachment":[{"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/media?parent=3811"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/categories?post=3811"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thedatastory.nl\/en\/wp-json\/wp\/v2\/tags?post=3811"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}