-
-
Save dvygolov/c2077f391bd15ba2f75d7496afb47a67 to your computer and use it in GitHub Desktop.
let api = 'https://graph.facebook.com/v14.0'; | |
let headers = { | |
"accept": "*/*", | |
"accept-language": "en-US,en;q=0.9", | |
"content-type": "application/x-www-form-urlencoded", | |
"sec-ch-ua": "\"Google Chrome\";v=\"107\", \"Chromium\";v=\"107\", \"Not=A?Brand\";v=\"24\"", | |
"sec-ch-ua-mobile": "?0", | |
"sec-ch-ua-platform": "\"Windows\"", | |
"sec-fetch-dest": "empty", | |
"sec-fetch-mode": "cors", | |
"sec-fetch-site": "same-site" | |
}; | |
var cbo = await campUsesCBO(); | |
await main(cbo); | |
async function campUsesCBO(){ | |
let accountId = require("BusinessUnifiedNavigationContext").adAccountID; | |
let f = await fetch(`${api}/act_${accountId}/campaigns?fields=bid_strategy&access_token=${__accessToken}`, { | |
"headers": headers, | |
"referrer": "https://business.facebook.com/", | |
"referrerPolicy": "origin-when-cross-origin", | |
"body": null, | |
"method": "GET", | |
"mode": "cors", | |
"credentials": "include" | |
}); | |
let camps = await f.json(); | |
if (camps.data.length==0) return false; | |
if (camps.data[0]?.bid_strategy??null!=null) | |
return true; | |
return false; | |
} | |
async function main(cbo){ | |
if (cbo) | |
alert("Your campaign uses CBO so we'll create auto-rules for campaigns!"); | |
else | |
alert("Your campaign does NOT use CBO so we'll create rules for adsets!"); | |
let accountId = require("BusinessUnifiedNavigationContext").adAccountID; | |
await clearRules(accountId); | |
let maxCPA = prompt('Please write your maximum CPA:'); | |
if (maxCPA == null) { | |
alert('Max CPA not set, exiting...'); | |
return; | |
} | |
let hour = parseInt(prompt(`At which hour should we switch ON ${cbo?"campaign":"adsets"}?`)); | |
if (hour == null) { | |
alert('Switch ON hour not set, exiting...'); | |
return; | |
} | |
let name = `TurnOff ${cbo?'Campaign':'Adset'} Withoud Leads`; | |
let evalSpec = { | |
"evaluation_type":"SCHEDULE", | |
"filters":[ | |
{"field":"spent","operator":"GREATER_THAN","value":(maxCPA*100).toString()}, | |
{"field":"offsite_conversion.fb_pixel_lead","operator":"LESS_THAN","value":"1"}, | |
{"field":"entity_type","value":`${cbo?'CAMPAIGN':'ADSET'}`,"operator":"EQUAL"}, | |
{"field":"time_preset","value":"TODAY","operator":"EQUAL"} | |
]}; | |
let execSpec = { | |
"execution_type":"PAUSE", | |
"execution_options":[{"field":"alert_preferences","value":{"instant":{"trigger":"CHANGE"}},"operator":"EQUAL"}] | |
}; | |
let schedSpec = {"schedule_type":"SEMI_HOURLY"}; | |
await addRule(accountId, name, evalSpec, execSpec, schedSpec); | |
name = `TurnOff ${cbo?'Campaign':'Adset'} With Expensive Leads`; | |
evalSpec = { | |
"evaluation_type":"SCHEDULE", | |
"filters":[ | |
{"field":"cost_per_lead_fb","operator":"GREATER_THAN","value":(maxCPA*100).toString()}, | |
{"field":"entity_type","value":`${cbo?'CAMPAIGN':'ADSET'}`,"operator":"EQUAL"}, | |
{"field":"time_preset","value":"TODAY","operator":"EQUAL"} | |
] | |
}; | |
execSpec = { | |
"execution_type":"PAUSE", | |
"execution_options":[ | |
{"field":"alert_preferences","value":{"instant":{"trigger":"CHANGE"}},"operator":"EQUAL"} | |
]}; | |
await addRule(accountId, name, evalSpec, execSpec, schedSpec); | |
name = `TurnOn ${cbo?'Campaign':'Adset'} With Cheap Leads`; | |
evalSpec = { | |
"evaluation_type":"SCHEDULE", | |
"filters":[ | |
{"field":"cost_per_lead_fb","operator":"LESS_THAN","value":(maxCPA*100).toString()}, | |
{"field":"offsite_conversion.fb_pixel_lead","operator":"GREATER_THAN","value":"0"}, | |
{"field":"entity_type","value":`${cbo?'CAMPAIGN':'ADSET'}`,"operator":"EQUAL"}, | |
{"field":"time_preset","value":"TODAY","operator":"EQUAL"} | |
] | |
}; | |
execSpec = { | |
"execution_type":"UNPAUSE", | |
"execution_options":[ | |
{"field":"alert_preferences","value":{"instant":{"trigger":"CHANGE"}},"operator":"EQUAL"} | |
]}; | |
await addRule(accountId, name, evalSpec, execSpec, schedSpec); | |
name = `TurnOn All ${cbo?'Campaigns':'Adsets'} at ${hour}`; | |
evalSpec = { | |
"evaluation_type":"SCHEDULE", | |
"filters":[{"field":"entity_type","value":`${cbo?'CAMPAIGN':'ADSET'}`,"operator":"EQUAL"},{"field":"time_preset","value":"MAXIMUM","operator":"EQUAL"}] | |
}; | |
execSpec = { | |
"execution_type":"UNPAUSE", | |
"execution_options":[ | |
{"field":"alert_preferences","value":{"instant":{"trigger":"CHANGE"}},"operator":"EQUAL"} | |
]}; | |
schedSpec = { | |
"schedule_type":"CUSTOM", | |
"schedule":[ | |
{"days":[0],"start_minute":hour*60,"end_minute":hour*60}, | |
{"days":[1],"start_minute":hour*60,"end_minute":hour*60}, | |
{"days":[2],"start_minute":hour*60,"end_minute":hour*60}, | |
{"days":[3],"start_minute":hour*60,"end_minute":hour*60}, | |
{"days":[4],"start_minute":hour*60,"end_minute":hour*60}, | |
{"days":[5],"start_minute":hour*60,"end_minute":hour*60}, | |
{"days":[6],"start_minute":hour*60,"end_minute":hour*60} | |
] | |
}; | |
await addRule(accountId, name, evalSpec, execSpec, schedSpec); | |
let createCpcRules = confirm('Do you want to create rules based on Max CPC?'); | |
if (createCpcRules){ | |
let maxCPC = prompt("Enter your maximum CPC (for example 0.13):"); | |
let maxClicks = prompt(`Enter clicks limit after which the ${cbo?'campaign':'adset'} will be shut down:`); | |
name = `TurnOff ${cbo?'Campaign':'Adset'} With Expensive CPC`; | |
evalSpec = { | |
"evaluation_type":"SCHEDULE", | |
"filters":[ | |
{"field":"clicks","operator":"GREATER_THAN","value":(maxClicks).toString()}, | |
{"field":"cpc","operator":"GREATER_THAN","value":(maxCPC*100).toString()}, | |
{"field":"entity_type","value":`${cbo?'CAMPAIGN':'ADSET'}`,"operator":"EQUAL"}, | |
{"field":"time_preset","value":"TODAY","operator":"EQUAL"} | |
]}; | |
execSpec = { | |
"execution_type":"PAUSE", | |
"execution_options":[{"field":"alert_preferences","value":{"instant":{"trigger":"CHANGE"}},"operator":"EQUAL"}] | |
}; | |
schedSpec = {"schedule_type":"SEMI_HOURLY"}; | |
await addRule(accountId, name, evalSpec, execSpec, schedSpec); | |
} | |
let createCpmRules = confirm('Do you want to create rules based on Max CPM?'); | |
if (createCpmRules){ | |
let maxCPM = prompt("Enter your maximum CPM:"); | |
let maxImpressions = prompt(`Enter your maximum impressions after which the ${cbo?'campaign':'adset'} will be shut down:`); | |
name = `TurnOff ${cbo?'Campaign':'Adset'} With Expensive CPM`; | |
evalSpec = { | |
"evaluation_type":"SCHEDULE", | |
"filters":[ | |
{"field":"impressions","operator":"GREATER_THAN","value":maxImpressions.toString()}, | |
{"field":"cpm","operator":"GREATER_THAN","value":(maxCPM*100).toString()}, | |
{"field":"entity_type","value":`${cbo?'CAMPAIGN':'ADSET'}`,"operator":"EQUAL"}, | |
{"field":"time_preset","value":"TODAY","operator":"EQUAL"} | |
]}; | |
execSpec = { | |
"execution_type":"PAUSE", | |
"execution_options":[{"field":"alert_preferences","value":{"instant":{"trigger":"CHANGE"}},"operator":"EQUAL"}] | |
}; | |
schedSpec = {"schedule_type":"SEMI_HOURLY"}; | |
await addRule(accountId, name, evalSpec, execSpec, schedSpec); | |
} | |
alert('All Done!'); | |
} | |
async function getAllRules(accountId){ | |
let f = await fetch(`${api}/act_${accountId}/adrules_library?access_token=${__accessToken}`, { | |
"headers": headers, | |
"referrer": "https://business.facebook.com/", | |
"referrerPolicy": "origin-when-cross-origin", | |
"body": null, | |
"method": "GET", | |
"mode": "cors", | |
"credentials": "include" | |
}); | |
let rules = await f.json(); | |
return rules; | |
} | |
async function deleteRule(ruleId){ | |
let f = await fetch(`${api}/${ruleId}?access_token=${__accessToken}&method=delete`, { | |
"headers": headers, | |
"referrer": "https://business.facebook.com/", | |
"referrerPolicy": "origin-when-cross-origin", | |
"body": "method=delete", | |
"method": "POST", | |
"mode": "cors", | |
"credentials": "include" | |
}); | |
let js = await f.json(); | |
console.log(js); | |
} | |
async function clearRules(accountId){ | |
let rules = await getAllRules(accountId); | |
let rulesCount = rules.data.length; | |
if (rulesCount==0) return; | |
let clear = confirm(`Do you want to clear all existing autorules (${rulesCount} found)?`); | |
if (!clear) return; | |
console.log(`Deleting ${rulesCount} rules.`); | |
for (const rule of rules.data) { | |
console.log(`Deleting rule ${JSON.stringify(rule)}...`); | |
await deleteRule(rule['id']); | |
}; | |
} | |
async function addRule(accountId, name, evalSpec, execSpec, schedSpec){ | |
let body = { | |
"locale":"en_US", | |
"evaluation_spec":JSON.stringify(evalSpec), | |
"execution_spec":JSON.stringify(execSpec), | |
"name":name, | |
"schedule_spec":JSON.stringify(schedSpec), | |
"access_token":__accessToken, | |
"status":"ENABLED" | |
}; | |
let f = await fetch(`${api}/act_${accountId}/adrules_library?access_token=${__accessToken}`, { | |
"headers": headers, | |
"referrer": "https://business.facebook.com/", | |
"referrerPolicy": "origin-when-cross-origin", | |
"body": new URLSearchParams(body).toString(), | |
"method": "POST", | |
"mode": "cors", | |
"credentials": "include" | |
}); | |
let json = await f.json(); | |
console.log(`${name}: ${JSON.stringify(json)}`); | |
return json; | |
} |
Use this service to create a one-liner from this script.
After you got a one-liner use
javascript: (async () => { one-liner })();
to create a bookmarklet.
What a wonderful script! You're just GENIUS! Now I spend not 8 hours working a day but only 3 for run ads and then after all I do just chill
What a wonderful script! You're just GENIUS! Now I spend not 8 hours working a day but only 3 for run ads and then after all I do just chill
Haha, if that's true - lucky you are!
Yeah I am so happy find your scripts. My work became so easy. You should give me a chance to donate you bro, I didn't found where you collect donations
Yeah I am so happy find your scripts. My work became so easy. You should give me a chance to donate you bro, I didn't found where you collect donations
No problem, USDT TRC20: TKeNEVndhPSKXuYmpEwF4fVtWUvfCnWmra and thanks in advance)
Yeah I am so happy find your scripts. My work became so easy. You should give me a chance to donate you bro, I didn't found where you collect donations
No problem, USDT TRC20: TKeNEVndhPSKXuYmpEwF4fVtWUvfCnWmra and thanks in advance)
Donated. Thank you for making my work more easier :)
Sadly it doesn't work anymore :c
First of all you'll be asked if you want to remove all of your existing autorules. Click Ok or Cancel.
Then you'll be asked to enter maximum CPA that is ok for you.
After that you'll be asked to enter time in 24-hour format (for example, 2). At this time all of the switched off adsets will be switched on.
Here are all the rules that will be created:
UPD: Added 2 more rules for switching adsets with high CPC and CPM. They are optional, you can opt-out if you don't need them.