Dynamic Ad Extensions Script

Ad extensions are good. Updating ad extensions manually is bad. Hence this script, which automates ad extension updates. Imagine your extension is about price – those change all the time. Or you want to be topical, like when it’s Pancake Day or something, and then the day after it’s Valentine’s Day. Pretty time-consuming? Not with this beauty!

What’s included?

How does the script work?

It’s a two-part solution that we like to call dynamic ad extensions: a Google Sheet to define the sitelinks and callouts with variable placeholders, and the variables to insert into their text; and a Google Ads Script to turn those definitions into real extensions.

But why bother with the script? Why not just write out the extensions with a spreadsheet and copy them into Google Ads Editor manually? Because you don’t just run the script this once — you can schedule this to run as often as you want. When new campaigns and ad groups come along, the script will give them all the right extensions, and you don’t have to lift a finger.

And you’re not just writing one set of extensions — the variables can be changed. They’re in their own cells separate from the ad text, so you can update them however you like.

How do I use it?

There are lots of possible ways for this one. Here are some ideas:

  1. Use basic functions and the current time from NOW() (just make sure the spreadsheet has the right time zone!):
    • Change sitelinks by time of day — for example, show the most appropriate menu using =if(hour(now())<11,”Breakfast Menu”,if(hour(now())<17,”Lunch Menu”,”Dinner Menu”))
    • Get seasonal text and final URLs based on the date. Automatically change sitelinks from Summer Dresses to Autumn Coats to Christmas Sweaters.
    • Set up countdowns.
  2. Be a bit more fancy, and use Google Sheet’s functions to import data:
    • IMPORTFEED can access RSS and ATOM feeds.
    • IMPORTHTML, IMPORTDATA or IMPORTXML can use any URL that has data in the right format.
    • GOOGLEFINANCE can get currency conversions and stock information (and if you want to see it in action, see our currency converter dashboard).
  3. Fancier still, write a Google Apps Script within the spreadsheet to fill in the variable cells:
    • Use UrlFetchApp to get data from your site. For example, rather than a sitelink saying, “Wide Range Available,” you could check the actual number available and put that into the sitelink.
    • The Shopping Content Service lets you get data from your Merchant Center’s shopping feed — for example, you could show your cheapest prices or make sure sitelinks point to things that are in stock.
    • Use the Drive service to get data from your files stored in Google Drive. This could get you any information you can think of.
  4. Or, simplest of all, you could just manually update the cells! You still have benefit of knowing all extensions are updated and are applied to all applicable campaigns or groups.

You can also add new sitelinks and callouts to the sheet whenever you feel like it. The script checks which of the extensions already exist, and it creates them if they don’t. You can also change which campaigns or ad groups the extensions get attached to (but the script won’t detach extensions from campaigns that aren’t covered any more — you’ll have to do that yourself).

Once an extension is created, the script will update it, rather than create a new one (There’s a hidden column that will automagically fill with extension IDs). So if there’s a campaign that’s not covered by the settings in the spreadsheet but uses the same sitelinks, it will still be updated.

So, you want to try this out for yourself? First go to the template sheet — in the File menu, click “Make a copy” to get a version for yourself. In your version, replace the example extensions with the details for your extensions:

  1. The Sitelinks tab has columns for Dynamic Headline, Dynamic DL1 (for description line 1), Dynamic DL2 (for description line 2) and Dynamic URL. The Callouts tab has a column for Dynamic Callout (for the callout text). You can fill these in with the text you want for your extensions. Where you’d like to have variable text, you use {variable column name:default text}.
    • For sitelinks, you can leave the description lines blank, but not the headline or URL.
  2. The next columns give the variables. Callouts only have two variables, var1 and var2. As sitelinks have more text to fill in, they can have up to five variables: the columns var1 to var5.
    • For example, if the Dynamic Headline said {var1:Many} {var2:Seasonal} Dresses, var1 said “302” and var2 said “Summer”, then the script would create a sitelink with the headline 302 Summer Dresses. If var1 is “300000002” — which would be too long to fit — the script would use the default text instead, making the headline Many Summer Dresses.
  3. In the Sitelinks tab, the next columns are Headline, DL1, DL2 and URL; in the Callouts tab, the next column is Callout. You don’t fill in these columns — every time it runs, the script will fill them in with the actual values currently being used.
  4. Mobile Preferred can be Yes or No, depending on whether you want the extension to be mobile-preferred or not.
  5. Entity level is either Campaign or Ad Group, depending on which level you want your extensions.
  6. The next columns are used to pick which campaign/ad group the extensions will be attached to:
    • If you want the extensions in just one campaign/ad group, then fill its exact name into Entity name is.
    • If you’d like the extensions in all campaigns/ad groups with a certain word or phrase in the name, then put it under Entity name contains.
    • If you’d like the extensions in all campaigns/ad groups except those with a certain word or phrase in the name, then put it under Entity name excludes.
    • If you’d like the extensions in all campaigns/ad groups with a certain label, then put the label name in Entity has label. Make sure you type it precisely correctly — the capitalization does matter for labels.
  7. If the Entity level is Ad Group, then you can also fill in Parent is, Parent contains and Parent excludes — these are like Entity name is, Entity name contains and Entity name excludes, except they are used to filter the campaign name rather than the ad group name.

Once you have the spreadsheet set up, go to your Google Ads account and copy and paste the script. Then there are a couple of settings at the top of the script:

  • Change spreadsheetUrl to the URL of your version of the spreadsheet.
  • If there’s a problem with running the script — for example, a campaign label has disappeared, or some part of the extension text was too long — then an email will be sent to all of the addresses in emailRecipients. These addresses should be surrounded by quotes and comma-separated. Alternatively, if you don’t want errors to be emailed, you can leave the array empty.

The first run will create the extensions. Then you can set up a schedule, so it can run as frequently as you think is necessary: every time the script runs, it will update the extensions and make sure they’re attached to everything that needs them.

(Note that if you’ve not run the script before, you can do a preview run to see what the extensions will look like. But it won’t show which campaigns the extensions will be attached to — to do that, the extensions need to actually be created, and they won’t be created in a preview run.)

The Dynamic Ad Extensions Script code