Google Ads scripts support campaign drafts and experiments, which are used to prepare and test changes to Search and Display Network campaigns. A draft is a clone of an existing campaign that does not serve its own ads but can be used to stage changes without modifying the original campaign. The staged changes can then be applied to the base campaign.
If you want to take it a step further, you can turn the draft into an experiment (also known as "trials" in the AdWords API). The experiment campaign runs parallel to the original campaign, showing its ads to a specified percentage of traffic.
Based on the results of the experiment, you can apply the changes to the original campaign, branch the experiment to an independent campaign, or abandon the experiment campaign.
This guide explains the basic workflow for working with drafts and experiments in a script.
Drafts
Creating a draft
A draft is made from an existing base campaign by using a
DraftBuilder
and providing a unique name. The base campaign must be a Search, Search with Display
Select, or Display campaign (excluding Mobile App campaign for the Display
Network), and it must not have a shared budget.
var campaign = AdsApp.campaigns()
.withCondition("Name = 'INSERT_CAMPAIGN_NAME_HERE'")
.get()
.next();
var draftBuilder = campaign.newDraftBuilder()
.withName("INSERT_DRAFT_NAME_HERE")
.build();
var draft = draftBuilder.getResult();
DraftBuilder.build()
returns a DraftOperation
,
a typical operation in Scripts. See our guide to builders
for more details.
A draft
is uniquely identified by the combination of its base campaign ID
and draft ID. See DraftSelector.withIds()
for more information.
Provisioning the draft campaign
A draft
object relates a base campaign and a draft campaign. To stage updates
to the base campaign, you propagate changes through the draft campaign.
A draft campaign, like any other campaign, has methods to get and set its various attributes such as criteria, ad groups, bids, and ads.
var draftCampaign = draft.getDraftCampaign();
draftCampaign.setAdRotationType("CONVERSION_OPTIMIZE");
draftCampaign.createNegativeKeyword("shoes");
Keep in mind that policy checks for ads are done for a draft campaign just as they are for the base campaign. You will not be able to run an experiment from a draft campaign that has policy-violating ads.
Executing the draft
After provisioning the draft campaign, you can do one of the following:
If you don't want to use the changes, you can simply remove the draft. Removing the draft is irreversible, but it can still be viewed under All drafts in the drafts tab of the Google Ads UI.
draft.remove();
If you decide to keep the changes you made in the draft, you can go ahead and apply them:
draft.startApplying();
This method starts the process of applying the updates to the base campaign, so the draft will appear to have status "Applying..." in the Google Ads UI. However, the method will NOT notify you when the process completes.
Although there is little you can do with an applied draft, if you do have a use for it later, we suggest scheduling the script for a future run and checking that its status has become
APPLIED
. See our best practices guide for more details.If you would like to test out your changes first, you can use the draft to create an experiment.
Experiments
Creating an experiment
An experiment
is built from a draft
, and is the manager of an experiment
campaign. You create an experiment
with an
ExperimentBuilder
and by providing a traffic split percentage and unique name.
The traffic split percentage determines what portion of traffic will be shown ads from the experiment campaign instead of the base campaign. For this reason, each base campaign can have only one running experiment at a time.
var experimentBuilder = draft.newExperimentBuilder();
experimentBuilder.withName("INSERT_EXPERIMENT_NAME_HERE")
.withTrafficSplitPercent(50)
.startBuilding();
Note that ExperimentBuilder.startBuilding()
does not return an operation like other Builder.build()
calls. However,
you can see the status of your new experiment's creation by navigating to the
experiments tab of the Google Ads UI. The experiment will appear to have status
"Creating...". To interact with the experiment in a script, schedule a run in
the future or wait until the experiment's status becomes "Active" or "Scheduled"
in the Google Ads UI. See the best practices
guide for more details.
// Some time in a future run, either manual or scheduled.
var experiment = AdsApp.experiments()
.withCondition("Name = 'INSERT_EXPERIMENT_NAME_HERE'")
.get()
.next();
Unlike drafts, experiments are uniquely identified by a single ID. See
ExperimentSelector.withIds()
for more information.
Provisioning the experiment campaign
Similar to a draft
, an experiment
itself is not a campaign. Rather, it
relates the base campaign, the draft, and the experiment campaign. Fields
of an experiment campaign are modifiable, with the following exceptions:
- name
- status
- start date
- end date
- budget
var experimentCampaign = experiment.getExperimentCampaign();
// Will succeed.
experimentCampaign.setAdRotationType("ROTATE_FOREVER");
experimentCampaign.createNegativeKeyword("sneakers");
// Will fail.
experimentCampaign.setName("INSERT_EXPERIMENT_NAME_HERE");
Changes to the name, start date, and end date can be made to the experiment (referred to as 'Trials' in Google Ads API), after which they will propagate to the experiment campaign. Unless specified at creation time, the start date and end date of an experiment will default to those of its base campaign. When updated, the new start or end date must be within the base campaign's.
// Will succeed.
experiment.setName("INSERT_EXPERIMENT_NAME_HERE");
// Will succeed if date is acceptable.
var date = "20180101";
experiment.setStartDate(date);
After the experiment ends
At your experiment's completion, you have a few options. We recommend letting the experiment completely finish so that it will stop serving ads but you can still interact with it. A "Finished" experiment can still be removed, applied, or graduated, and its campaign's performance stats are still accessible.
experiment.finish();
var stats = experimentCampaign.getStatsFor("INSERT_TIME_PERIOD_HERE");
If you're dissatisfied with the experiment based on the stats, you can remove the experiment, which also removes the experiment campaign. Removing the experiment is irreversible, but it can still be viewed under All experiments in the experiments tab of the Google Ads UI.
experiment.remove();
If you're satisfied with the experiment's results, you have two options:
You can start applying the changes and just as with drafts, you won't be notified when the process completes.
experiment.startApplying();
You can establish the experiment campaign as an independent, fully-operating campaign, without affecting the base campaign. This process, known as graduation, completes immediately and requires a new budget to be set.
var budget = AdsApp.budgets() .withCondition("BudgetId = 'INSERT_BUDGET_ID_HERE'") .get() .next(); experiment.graduate(budget);
The new campaign can no longer share a budget with the base campaign, which necessitates the new budget. Graduated campaigns are just like normal campaigns in that all their fields are modifiable and that they can serve as a base campaign for more drafts and experiments.
Considerations
The notion of base entities
The introduction of drafts and experiments to Google Ads scripts also introduces
the notion of base entities. Draft and experiment campaigns and the ad groups in
them are distinct from their original base campaigns, which is why
Campaign
and
AdGroup
now have methods to access their base campaign and ad group:
getBaseCampaign()
and getBaseAdGroup()
. The methods simply
return the calling entity if called by a base campaign or an ad group in one.
Entities within campaigns and ad groups, such as keywords and ads, also have
been given such methods.
With this notion in mind, to help keep track, campaigns have been given
isBaseCampaign()
,
isDraftCampaign()
,
and isExperimentCampaign()
methods.
The new Campaign.draftCampaigns()
and Campaign.experimentCampaigns()
methods allow you to access all the draft campaigns and experiment campaigns,
respectively, that have the calling campaign as their base campaign. In a
similar vein, CampaignSelector.withCondition()
can now
filter on the CampaignExperimentType
column, using one of BASE
, DRAFT
, and
EXPERIMENT
as the possible values:
// Get all draft campaigns in the account.
var allDraftCampaigns = AdsApp.campaigns()
.withCondition("CampaignExperimentType = DRAFT")
.get();
Error handling
Some actions involving drafts and experiments will succeed when the script is run,
but might fail after the asynchronous call is executed. These methods are
Draft.startApplying()
, Experiment.startApplying()
, and ExperimentBuilder.startBuilding()
.
You should wait to check whether these operations succeed. The Google Ads UI will
show the statuses "Applied" or "Active" after successful completions of
startApplying()
and startBuilding()
, respectively. It will show "Unable to apply"
or "Unable to create" upon failure, and let you click to see what errors occurred.
Also, some errors that occur when working with drafts and experiments may not appear when a script is previewed, but only when it is actually run. This would occur, for example, when attempting to make an experiment from a draft that already has one:
Logger.log(draft.hasRunningExperiment()); // Logs true.
draft.newExperimentBuilder()
.withName("FAULTY_EXPERIMENT")
.withTrafficSplitPercent(50) // Succeed in preview mode,
.startBuilding(); // but will fail when run.
It's also possible that some methods fail in the preview stage, but succeed after they run; for instance, after creating a draft:
var draftCampaign = draft.getDraftCampaign();
draftCampaign.createNegativeKeyword("shoes"); // Will fail in preview.
This will fail in preview mode as it cannot access the campaign immediately.
For this reason, we remind you to check the logs below your list of scripts after running them, and try running the script if you believe there is no flaw in your script but preview mode has failed.
Code snippets
Be sure to check out the relevant code snippets page for more examples using this feature.