A sheet can call the API without the key ever sitting in a cell.
Google Sheets' IMPORTDATA takes a URL and nothing else, so it cannot send the Authorization header, and the API does not accept keys in URLs. A key in a cell is readable by anyone the sheet is shared with, and Sheets refetches on its own schedule, which would spend your plan's lookups with nobody clicking anything. The recipe below keeps the key in script properties, sends the header, and caches each answer for six hours.
// getdomaindata.com custom functions for Google Sheets.
// 1. Extensions > Apps Script. Paste this whole file and save.
// 2. Replace PASTE_YOUR_KEY below, choose setKey in the toolbar and press Run once, then
// delete the key from the code and save again. It now lives in Script Properties,
// never in a cell and never in the sheet's history.
// 3. In any cell: =GDD_TECH("allbirds.com")
const BASE = "https://getdomaindata.com/api/v1";
function setKey() {
PropertiesService.getScriptProperties().setProperty("GDD_KEY", "gdd_live_PASTE_YOUR_KEY");
}
function gdd_(path) {
const cache = CacheService.getScriptCache();
const hit = cache.get(path);
if (hit) return JSON.parse(hit);
const key = PropertiesService.getScriptProperties().getProperty("GDD_KEY");
if (!key) throw new Error("Run setKey once with your API key.");
const r = UrlFetchApp.fetch(BASE + path, {
headers: { Authorization: "Bearer " + key },
muteHttpExceptions: true,
});
const body = JSON.parse(r.getContentText() || "{}");
if (r.getResponseCode() !== 200) throw new Error(body.error || ("HTTP " + r.getResponseCode()));
// Six hours. A sheet recalculates often; without this every recalculation would spend lookups.
cache.put(path, JSON.stringify(body.data), 21600);
return body.data;
}
/** Technologies detected on a domain, comma-separated. */
function GDD_TECH(domain) {
return (gdd_("/domain/" + encodeURIComponent(domain)).technologies || []).join(", ");
}
/** Our latest estimated monthly visits, or blank when we hold no estimate. */
function GDD_TRAFFIC(domain) {
const d = gdd_("/domain/" + encodeURIComponent(domain));
return d.traffic ? d.traffic.estimated_monthly_visits : "";
}
/** Our latest employee estimate as a point or a range, or blank. */
function GDD_EMPLOYEES(domain) {
const d = gdd_("/domain/" + encodeURIComponent(domain));
if (!d.employees) return "";
const e = d.employees;
return e.point != null ? e.point : e.low + " to " + (e.high == null ? "more" : e.high);
}Then in a cell: =GDD_TECH(A2), =GDD_TRAFFIC(A2) or =GDD_EMPLOYEES(A2). The three functions share one cached call per domain, so a row with all three spends one lookup. A blank means we hold no estimate for that domain; an error message in the cell is the API's error code, explained on the errors page.
Power Query sends headers natively. Data, Get Data, Blank Query, then Advanced Editor:
let
key = "gdd_live_PASTE_YOUR_KEY",
Source = Json.Document(
Web.Contents("https://getdomaindata.com/api/v1/domain/allbirds.com",
[Headers = [Authorization = "Bearer " & key]])),
data = Source[data]
in
dataMove the key into a query parameter rather than leaving it in the editor if the workbook is shared. Each refresh spends one lookup per query.