{"id":9764,"date":"2023-06-05T13:46:28","date_gmt":"2023-06-05T13:46:28","guid":{"rendered":"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/"},"modified":"2023-06-05T13:46:28","modified_gmt":"2023-06-05T13:46:28","slug":"this-google-ads-script-uses-gpt-to-summarize-account-performance","status":"publish","type":"post","link":"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/","title":{"rendered":"This Google Ads script uses GPT to summarize account performance"},"content":{"rendered":"<p>Last month, I shared my first <a href=\"https:\/\/searchengineland.com\/google-ads-script-gpt-responsive-search-ads-395548\" target=\"_blank\" rel=\"noopener\">GPT-enabled Google Ads script<\/a>. It identifies missing RSA headlines and suggests new variants.<\/p>\n<p>This month, I wanted to push the limits of GPT a little harder and see if I could get it to write my next script for me. Spoiler alert: It worked! But it needed some handholding to get there. I\u2019ll teach you how I engineered the prompt to get a successful result.<\/p>\n<p>The script I am sharing uses OpenAI\u2019s GPT to write an account performance summary along with some suggestions for how to improve the performance of a Google Ads account.<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_81 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/#Making_PPC_reports_more_descriptive\" >Making PPC reports more descriptive<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/#GPTs_truth_problem\" >GPT\u2019s truth problem<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/#How_to_provide_GPT_with_facts_about_your_business\" >How to provide GPT with facts about your business<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/#Prompt_engineering\" >Prompt engineering<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/#Getting_GPT_to_write_Ads_scripts\" >Getting GPT to write Ads scripts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/#Using_GPT_in_Google_Ads_scripts\" >Using GPT in Google Ads scripts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/#Putting_it_together\" >Putting it together<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/craighordlow.com\/index.php\/2023\/06\/05\/this-google-ads-script-uses-gpt-to-summarize-account-performance\/#Summarizing_PPC_performance_with_GPT\" >Summarizing PPC performance with GPT<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Making_PPC_reports_more_descriptive\"><\/span>Making PPC reports more descriptive<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><a href=\"https:\/\/searchengineland.com\/guide\/what-is-paid-search\" target=\"_blank\" rel=\"noopener\">PPC<\/a> reporting can be a tedious task. By nature, it\u2019s also repetitive because clients and stakeholders expect the latest report in their inbox regularly \u2013 be it weekly, monthly, or, heaven forbid, even daily.<\/p>\n<p>There are plenty of great reporting tools (I work for one). While they can automate pulling in the data and visualizing it, making sense of and telling a story with the data usually still require a human\u2019s touch. GPT excels at writing compelling stories, so it seemed like a good solution for my problem. <\/p>\n<p>GPT and generative AI are adept at producing well-written text. Because <a href=\"https:\/\/searchengineland.com\/seo-guide-large-language-models-413227\" target=\"_blank\" rel=\"noopener\">large language models<\/a> (LLMs) have read billions of words, they\u2019re very good at predicting how to put words together in a way that makes for a compelling read.<\/p>\n<p>But as compelling as they may be, they\u2019re not always true, and that\u2019s a big problem when the goal is to share trustworthy reports with clients. <\/p>\n<p>So I set out to figure out if I could force GPT to be correct and a great storyteller about the data in an ads account.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"GPTs_truth_problem\"><\/span>GPT\u2019s truth problem<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>A weakness of GPT is that its core strength is predicting the next word in a string. It\u2019s much less reliable when it comes to fact-checking and ensuring what it says is correct.<\/p>\n<p>Its training might have included dozens of blog posts about how to get more conversions in Google Ads. <\/p>\n<p>Because those articles probably frequently mention tasks like checking budgets and managing CPA targets, GPT will likely include those things when it generates advice related to getting more conversions.\u00a0<\/p>\n<p>But it may get the details slightly wrong, like whether an advertiser whose CPA is lower than the target CPA should <em>increase<\/em> or <em>decrease<\/em> their ad budget. GPT isn\u2019t solving a problem analytically but rather predicting the words to include in its advice.<\/p>\n<p>Another problem is that GPT remains bad at math despite openAI\u2019s work to address this known problem. <\/p>\n<p>For example, if provided with facts like how many clicks and impressions a campaign has, it\u2019s not safe to assume that it will know how to determine the correct CTR from this information. We all know it\u2019s a simple formula: clicks\/impressions = CTR. <\/p>\n<p>Sometimes GPT will get it right, but there\u2019s no guarantee.<\/p>\n<p>To avoid calculation errors, I decided it would be safer to do the math myself and provide the results in the prompt. <\/p>\n<p>Rather than trusting GPT to calculate metrics like CTR, conversion rate, etc., correctly, I provided the values for those metrics in the prompt.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"How_to_provide_GPT_with_facts_about_your_business\"><\/span>How to provide GPT with facts about your business<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The specific task I wanted to automate was describing how an account\u2019s performance changed last month compared to the month before and including some optimization suggestions.<\/p>\n<p>When creating this automation, I couldn\u2019t jump straight into the code. I had to manually create a process that worked before turning that process into an automation. <\/p>\n<p>The first step was to experiment with GPT to determine what data it needed so it would stop making up facts and instead rely on the truth for crafting its stories. This required giving it Google Ads data with the facts I wanted it to describe.\u00a0<\/p>\n<p>Fortunately, GPT can take a table as input and figure out how to interpret the various cells. So I created a table of campaign performance and exported it as a CSV text file which could be copied and pasted into a GPT prompt.\u00a0<\/p>\n<p>Because I wanted GPT to comment on the changes in performance between two date ranges, I initially brought in two separate CSV strings, one for each period. <\/p>\n<p>But two separate CSV strings use more tokens than the same data combined into a single CSV with separate columns for different date ranges. <\/p>\n<p>So to make the automation slightly better at working with bigger accounts, I generated the combined CSV string.<\/p>\n<p>With factual data ready to insert into a prompt, I could then move on to engineer the prompt to give me the best results possible.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Prompt_engineering\"><\/span>Prompt engineering<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>With factual data to work with, I next needed to tell GPT what to do with those facts. The prompt could be as simple as: <\/p>\n<p>\u201cWrite a summary of the campaigns\u2019 performance comparing the two periods.\u201d<\/p>\n<p>GPT is smart and figures out what the different periods in the CSV data are. <\/p>\n<p>If it tends to focus too much on certain metrics you\u2019d like to deprioritize, add more detail to the prompt, like:<\/p>\n<p>\u201cDo not include Search Lost IS in the summary.\u201d<\/p>\n<p>Next, I wanted it to include some optimization tips. To make the suggestions more reliable and more in line with my own management style, I loaded the prompt with some additional facts like these:<\/p>\n<p>The target CPA is $20. A cost higher is bad, and a cost lower is good.<\/p>\n<p>If the Search lost IS (budget) &gt; 10% and the CPA is below the target, the budget should be raised.<\/p>\n<p>if the CPA is above the target, the bids should be adjusted.<\/p>\n<p>Then when sending a very detailed prompt with CSV data, facts, and a request for what to do with this data, GPT started giving solid answers. <\/p>\n<p>With all the puzzle pieces in place, it was time to ask GPT to write me the automation.<\/p>\n<p><!-- START INLINE FORM --><\/p>\n<div class=\"nl-inline-form border py-2 px-1 my-2\">\n<div class=\"row align-items-center\">\n<div class=\"col-12 col-lg-3 col-xl-4 pe-md-0 pb-2 pb-lg-0\">\n<p class=\"inline-form-text text-center mb-0\">Get the daily newsletter search marketers rely on.<\/p>\n<\/div>\n<div class=\"col-12 col-lg-7 col-xl-6  pe-lg-0\">\n<div class=\"form-nl-inline\">\n<div class=\"row g-0\">\n<div class=\"form-group col-12 col-lg-8 mb-0\"><\/div>\n<div class=\"col-12 col-lg-4 col-xl-4 mb-0\">\n<div class=\"d-none\">\n<p>Processing\u2026Please wait.<\/p>\n<\/div>\n<p>\t\t\t\t\t\t\t<button class=\"btn btn-dark inlineButton w-100 rounded-0 font-weight-bold\">SUBSCRIBE<\/button>\n\t\t\t\t\t\t<\/p><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"col-12 col-lg-2 col-xl-2 ps-1\">\n<p class=\"text-center mb-0\"><a class=\"nl-terms\" href=\"https:\/\/searchengineland.com\/termsofuse\" target=\"_blank\" rel=\"noopener noreferrer\">See terms.<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!-- END INLINE FORM --><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Getting_GPT_to_write_Ads_scripts\"><\/span>Getting GPT to write Ads scripts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The code for a Google Ads script to pull data from an account isn\u2019t particularly complicated. It\u2019s part of almost any script and very well documented. <\/p>\n<p>So I crossed my fingers and asked GPT to write a script to pull the data for me with this prompt:<\/p>\n<div class=\"wp-block-image\">\n<\/div>\n<p>The response looked like a good script, but one thing seemed a bit off. It was writing a GAQL query that included the two date ranges I wanted to compare in a single query. That is not supposed to work.<\/p>\n<div class=\"wp-block-image\">\n<\/div>\n<p>So I asked GPT to try again, and while the implementation changed slightly, it once again messed up the date ranges in the GAQL query:<\/p>\n<div class=\"wp-block-image\">\n<\/div>\n<p>At this point, I could have given up and fixed the code myself, but instead, I did some prompt engineering.<\/p>\n<p>What if my prompt was confusing GPT? <\/p>\n<p>I told it to:<\/p>\n<p>\u201cGet the clicks, impressions, cost, CTR, average CPC, conversions, conversion rate, and cost per conversion metrics <strong><em>for the previous month and the month before that.<\/em><\/strong>\u201d <\/p>\n<p>Could I be clearer and tell it this should be done in two separate queries that would be merged later?<\/p>\n<p>So I changed the prompt to include this new text: <\/p>\n<p>\u201cGet the clicks, impressions, cost, CTR, average CPC, conversions, conversion rate, and cost per conversion metrics. <strong><em>Get the report for 2 date ranges: last month and the month before that. build a map where the key is the campaign name and it includes the stats from the 2 date ranges.<\/em><\/strong>\u201d<\/p>\n<p>This is much more precise, and the result came back as follows:<\/p>\n<div class=\"wp-block-image\">\n<\/div>\n<p>Now GPT was writing the correct code. After installing it in my Google Ads account, it immediately worked as expected and generated the needed CSV data.<\/p>\n<p>This was a good lesson in prompt engineering for me. If you hire a new team member who\u2019s never done PPC, you probably need to be pretty precise in your instructions when you ask for help. It\u2019s the same with GPT, precision matters!<\/p>\n<p>Also, it still matters to be a subject matter expert. Someone who\u2019s never worked with GAQL or API reports from Google Ads might not know that you can\u2019t get data for two date ranges in a single call. Without that knowledge, finding the error in the GPT response could be very difficult.<\/p>\n<p>Bottom line, when asking GPT to generate code, it\u2019s helpful to write pseudo-code rather than being too general and only telling it what outputs you expect. The more you tell the system how to arrive at that output, the more likely it will write code that works.\u00a0<\/p>\n<p>With the code to pull CSV data working, I now needed some code to send that data to GPT to ask for a summary.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Using_GPT_in_Google_Ads_scripts\"><\/span>Using GPT in Google Ads scripts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>To use GPT in a script, you need API access and an API token. You can sign up for this on the <a href=\"https:\/\/platform.openai.com\/account\/api-keys\" target=\"_blank\" rel=\"noopener\">OpenAI website<\/a>. With that, you can write a simple function that calls the API with a prompt, gets the response, and prints it on the screen.<\/p>\n<p>This code could be requested from GPT, but I already had it from last month\u2019s RSA script so I just reused that.<\/p>\n<p>Here\u2019s the code snippet to use GPT in Google Ads scripts<\/p>\n\n<h2><span class=\"ez-toc-section\" id=\"Putting_it_together\"><\/span>Putting it together<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Next, I put the two scripts above together. The first script gets the data I need for my prompt, and the second script sends that data as a prompt to GPT and captures the response, which is then rendered on screen.<\/p>\n<p>Grab a copy of the complete code here and remember to add your own API key to start using it:<\/p>\n\n<p>Then you should experiment with the facts and prompt. The line in the code where you enter facts should include details you want GPT to know, such as: <\/p>\n<p>What your target is. <\/p>\n<p>Whether a number higher or lower than the target is good or bad. <\/p>\n<p>Facts about your account optimization methodology (i.e., what you would recommend doing if the CPA is too high and the impressions have decreased).<\/p>\n<p>GPT will pull from the facts you provided rather than making stuff up when it summarizes the performance.<\/p>\n<p>You can also engineer the prompt to do things the way you want. <\/p>\n<p>For example, you could ask GPT to include or exclude particular metrics in its summary or tell it what style to write in, e.g., conversational or business-oriented.<\/p>\n<p>Remember that this script uses the OpenAI API, which is <strong>not<\/strong> free. So every time you run this, it will cost money. <\/p>\n<p>I recommend running this script as needed and not putting it on an automated schedule.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Summarizing_PPC_performance_with_GPT\"><\/span>Summarizing PPC performance with GPT<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>GPT is excellent at writing but can have problems with factual correctness. That is why providing as many facts as possible in the prompts is helpful. <\/p>\n<p>By using a Google Ads script, facts about account performance can automatically be prepared in a format that works with GPT.<\/p>\n<p>Use this script to provide GPT with facts about your account and get a performance summary that can be shared with clients and stakeholders.<\/p>\n<p>I encourage you to check it out and let me know what you think.<\/p>\n<p>The post <a href=\"https:\/\/searchengineland.com\/google-ads-script-gpt-summarize-account-performance-427822\" target=\"_blank\" rel=\"noopener\">This Google Ads script uses GPT to summarize account performance<\/a> appeared first on <a href=\"https:\/\/searchengineland.com\/\" target=\"_blank\" rel=\"noopener\">Search Engine Land<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Last month, I shared my first GPT-enabled Google Ads script. It identifies missing RSA headlines and suggests new variants. This month, I wanted to push the limits of GPT a little harder and see if I could get it to write my next script for me. Spoiler alert: It worked! But it needed some handholding to get there. I\u2019ll teach you how I engineered the prompt to get a successful result. The script I am sharing uses OpenAI\u2019s GPT to write an account performance summary along [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"h5ap_radio_sources":[],"cybocfi_hide_featured_image":"","footnotes":""},"categories":[1],"tags":[],"class_list":["post-9764","post","type-post","status-publish","format-standard","hentry","category-best-seo-blogs"],"featured_image_src":null,"featured_image_src_square":null,"author_info":{"display_name":false,"author_link":"https:\/\/craighordlow.com\/author\/"},"_links":{"self":[{"href":"https:\/\/craighordlow.com\/index.php\/wp-json\/wp\/v2\/posts\/9764","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/craighordlow.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/craighordlow.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/craighordlow.com\/index.php\/wp-json\/wp\/v2\/comments?post=9764"}],"version-history":[{"count":0,"href":"https:\/\/craighordlow.com\/index.php\/wp-json\/wp\/v2\/posts\/9764\/revisions"}],"wp:attachment":[{"href":"https:\/\/craighordlow.com\/index.php\/wp-json\/wp\/v2\/media?parent=9764"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/craighordlow.com\/index.php\/wp-json\/wp\/v2\/categories?post=9764"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/craighordlow.com\/index.php\/wp-json\/wp\/v2\/tags?post=9764"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}