curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"landing_page": "https://example.com/furniture",
"geo_targets": [
"1023191"
],
"language_code": "en"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate"
payload = {
"landing_page": "https://example.com/furniture",
"geo_targets": ["1023191"],
"language_code": "en"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
landing_page: 'https://example.com/furniture',
geo_targets: ['1023191'],
language_code: 'en'
})
};
fetch('https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'landing_page' => 'https://example.com/furniture',
'geo_targets' => [
'1023191'
],
'language_code' => 'en'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate"
payload := strings.NewReader("{\n \"landing_page\": \"https://example.com/furniture\",\n \"geo_targets\": [\n \"1023191\"\n ],\n \"language_code\": \"en\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"landing_page\": \"https://example.com/furniture\",\n \"geo_targets\": [\n \"1023191\"\n ],\n \"language_code\": \"en\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"landing_page\": \"https://example.com/furniture\",\n \"geo_targets\": [\n \"1023191\"\n ],\n \"language_code\": \"en\"\n}"
response = http.request(request)
puts response.read_body{
"cpc_low_micros": 850000,
"cpc_high_micros": 2400000,
"currency_code": "USD",
"sample_size": 10
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Estimate Google Ads cost per click
Estimates what one click costs for a landing page in a set of locations, so you can turn a daily budget into a click range before a campaign exists.
Google publishes no click forecast for a Performance Max campaign before it launches, so this answers a narrower question. Base44 asks Google’s keyword planner for the keyword ideas it derives from landing_page, averages the top-of-page bid range over up to 10 of them, and takes 60% of that range, because a click usually costs less than the top-of-page bid. Divide a daily budget by cpc_high_micros and cpc_low_micros for the click range. Both are in the account’s budget currency, so no conversion is needed. To forecast a Smart campaign from its keyword themes instead, use Estimate a Google Ads campaign budget.
A sample_size of 0, with both figures 0, means Google had no keyword ideas it could price. Treat that as no estimate, not as free clicks.
The app needs a connected Google Ads account that has finished provisioning. An account with no Google customer ID yet, and a landing_page that is not an http or https URL, are rejected with a 400 before anything reaches Google. Nothing is saved and nothing is spent on ads.
This is limited to 30 requests a minute per app. Some workspaces have a different limit. It is refused with a 409 while the workspace is on a Google Ads billing hold.
curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"landing_page": "https://example.com/furniture",
"geo_targets": [
"1023191"
],
"language_code": "en"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate"
payload = {
"landing_page": "https://example.com/furniture",
"geo_targets": ["1023191"],
"language_code": "en"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
landing_page: 'https://example.com/furniture',
geo_targets: ['1023191'],
language_code: 'en'
})
};
fetch('https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'landing_page' => 'https://example.com/furniture',
'geo_targets' => [
'1023191'
],
'language_code' => 'en'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate"
payload := strings.NewReader("{\n \"landing_page\": \"https://example.com/furniture\",\n \"geo_targets\": [\n \"1023191\"\n ],\n \"language_code\": \"en\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"landing_page\": \"https://example.com/furniture\",\n \"geo_targets\": [\n \"1023191\"\n ],\n \"language_code\": \"en\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/google-ads/campaigns/cpc-estimate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"landing_page\": \"https://example.com/furniture\",\n \"geo_targets\": [\n \"1023191\"\n ],\n \"language_code\": \"en\"\n}"
response = http.request(request)
puts response.read_body{
"cpc_low_micros": 850000,
"cpc_high_micros": 2400000,
"currency_code": "USD",
"sample_size": 10
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Authorizations
Personal access token, sent as Authorization: Bearer <token>.
Path Parameters
ID of the app you are planning a Google Ads campaign for.
Body
Page the campaign sends clicks to, as an http or https URL. Google derives the keyword ideas it prices from this page. Required: anything else is rejected with a 400.
"https://example.com/furniture"
Locations to price clicks in, as Google geo target constant IDs (geoTargetConstants/1023191, or just 1023191). When you send more than 10, only 10 of them are priced, always the same 10 for the same set. Leave it empty to price all locations. If Google's keyword planner rejects the locations you send, the estimate covers all locations instead of failing.
["1023191"]
Two-letter code of the language the ads run in, which picks the keyword market. A regional tag like pt-BR is reduced to pt, and a missing or unsupported code prices in English. List Google Ads advertising languages returns the supported codes.
"en"
Response
The estimated cost of one click.
What a click is likely to cost for a landing page in a set of locations.
Low end of the estimated cost of one click, in micros of currency_code, so 850000 is 0.85. 0 when there is no estimate.
850000
High end of the estimated cost of one click, in micros of currency_code. 0 when there is no estimate.
2400000
Currency of both figures as a three-letter ISO 4217 code. It is the account's Google Ads budget currency, the same one campaign budgets are set in.
"USD"
How many of Google's keyword ideas the range is averaged over, at most 10. 0 means Google returned none it could price, so there is no estimate.
10
Was this page helpful?