There are campaign management tools that will allocate budget for you throughout the day, and then there is Google Ads Script.
This is an example script that we have used to ensure campaign budgets are spread across ad groups throughout the day in such a way that they will all get better distributed exposure.
function main() { // Set to the number of time slots per day to use as a basis for balancing ad groups const TIME_SLOTS = 8; const TIME_SLOT_DURATION = 24 / TIME_SLOTS; // Hours per slot // Define a minimum bid to prevent excessively low values const MIN_BID = 0.5; // Adjust based on your market // Get current time and determine the active time slot const now = new Date(); const currentHour = now.getHours(); const currentSlot = Math.floor(currentHour / TIME_SLOT_DURATION); // 0-indexed slot Logger.log(`Current time slot: ${currentSlot + 1}/${TIME_SLOTS}`); // Fetch all enabled campaigns const campaigns = AdsApp.campaigns() .withCondition("Status = ENABLED") .get(); while (campaigns.hasNext()) { const campaign = campaigns.next(); // Get the campaign's daily budget dynamically const campaignBudget = campaign.getBudget().getAmount(); const timeSlotBudget = campaignBudget / TIME_SLOTS; // Allocate evenly across time slots Logger.log( `Campaign "${campaign.getName()}" has a daily budget of ${campaignBudget}. Allocating ${timeSlotBudget} for this time slot.` ); // Fetch all enabled ad groups within the campaign const adGroups = campaign.adGroups() .withCondition("Status = ENABLED") .get(); const activeAdGroupsCount = adGroups.totalNumEntities(); if (activeAdGroupsCount === 0) continue; // Calculate the budget per ad group for the current time slot const adGroupBudget = timeSlotBudget / activeAdGroupsCount; while (adGroups.hasNext()) { const adGroup = adGroups.next(); // Fetch today's spend for the ad group const stats = adGroup.getStatsFor("TODAY"); const spendSoFar = stats.getCost(); // Calculate remaining budget for the ad group in this slot const remainingBudget = adGroupBudget - spendSoFar; // Fetch historical performance data for the ad group const historicalStats = adGroup.getStatsFor("LAST_7_DAYS"); const averageCpc = historicalStats.getAverageCpc(); // Fetch current CPC bid const currentCpc = adGroup.bidding().getCpc(); // Determine a new bid based on performance and remaining budget let newBid = currentCpc; if (remainingBudget > 0) { // Increase bid to encourage more spend, considering historical CPC and a minimum bid newBid = Math.max(currentCpc * 1.2, averageCpc, MIN_BID); } else { // Decrease bid to slow down spend newBid = Math.max(currentCpc * 0.8, MIN_BID); } // Update the ad group CPC bid adGroup.bidding().setCpc(newBid); Logger.log( `Adjusted bid for ad group "${adGroup.getName()}" to ${newBid}.` ); } } }
Watch out! This is going to modify all active campaigns. Preview and run in a safe area if you are unsure of what will happen. The script can be modified to pick up only some campaigns, of course, for example:
function main() { const remarketingCampaigns = AdsApp.campaigns() .withCondition("Name CONTAINS 'Remarketing'") .withCondition("Status = ENABLED") // Optional: Fetch only active campaigns .get(); while (remarketingCampaigns.hasNext()) { const campaign = remarketingCampaigns.next(); Logger.log(`Remarketing Campaign: ${campaign.getName()}`); } }
This would check through all active campaigns for one that has a name containing 'Remarketing'
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article