Clicks → Google Sheets overview

Pull advertiser click totals by date into Google Sheets. The Apps Script sample requires start_date and end_date (max 90 days), authenticates with X-Api-Key, and writes flat click rows to a Clicks tab.

Endpoint: GET /api/v1/clicks

Clicks responses return flat objects under data (not nested JSON:API attributes). start_date and end_date are required; ranges cannot exceed 90 days.

Setup in Google Sheets

  1. Open a Google Sheet → ExtensionsApps Script.
  2. Get your personal API key from API key docs. Prefer the X-Api-Key header (these samples already do).
  3. In Apps Script, open Project SettingsScript properties and add HIENERGY_API_KEY with your key value.
  4. Paste the shared client library, then the resource import script below.
  5. Click Save, reload the Sheet, and run the import from the Hi Energy AI menu (or Run in the editor).
  6. On first run, authorize the script when Google prompts for UrlFetchApp / external request permission.

1. Shared Apps Script client

Paste this helper library into your Apps Script project once. Every Hi Energy Google Sheets importer on this site reuses the same UrlFetchApp client, JSON:API flattener, and sheet writer.

/**
 * Hi Energy AI — shared Google Apps Script client
 * Paste this into Extensions → Apps Script, then add a resource script below.
 *
 * Setup:
 * 1. File → Project properties → Script properties
 * 2. Add property HIENERGY_API_KEY = your personal API key
 *    (from https://app.hienergy.ai/api_documentation/api_key)
 * 3. Optionally override HIENERGY_API_BASE if you use a custom host
 */

var HIENERGY_API_BASE = 'https://app.hienergy.ai';

function getHiEnergyApiKey_() {
  var key = PropertiesService.getScriptProperties().getProperty('HIENERGY_API_KEY');
  if (!key) {
    throw new Error(
      'Missing Script Property HIENERGY_API_KEY. ' +
      'Open Project Settings → Script properties and add your API key.'
    );
  }
  return key;
}

function hiEnergyApiGet_(path, query) {
  var url = HIENERGY_API_BASE + path;
  var params = [];
  Object.keys(query || {}).forEach(function(key) {
    var value = query[key];
    if (value === null || value === undefined || value === '') return;
    params.push(encodeURIComponent(key) + '=' + encodeURIComponent(String(value)));
  });
  if (params.length) url += '?' + params.join('&');

  var response = UrlFetchApp.fetch(url, {
    method: 'get',
    headers: {
      'X-Api-Key': getHiEnergyApiKey_(),
      'Accept': 'application/json'
    },
    muteHttpExceptions: true,
    followRedirects: true
  });

  var code = response.getResponseCode();
  var body = response.getContentText();
  var json = null;
  try { json = JSON.parse(body); } catch (e) {}

  if (code < 200 || code >= 300) {
    var message = (json && (json.error || json.message)) || body;
    throw new Error('Hi Energy AI API HTTP ' + code + ': ' + message);
  }
  return json;
}

function flattenJsonApiItem_(item) {
  var row = {};
  if (!item || typeof item !== 'object') return row;
  if (item.id !== undefined) row.id = item.id;
  if (item.type !== undefined) row.type = item.type;
  var attrs = item.attributes || {};
  Object.keys(attrs).forEach(function(key) {
    var value = attrs[key];
    row[key] = (value !== null && typeof value === 'object') ? JSON.stringify(value) : value;
  });
  return row;
}

function extractJsonApiCollection_(payload, preferredKeys) {
  if (!payload) return [];
  var keys = preferredKeys || ['data'];
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    var node = payload[key];
    if (Array.isArray(node)) return node;
    if (node && Array.isArray(node.data)) return node.data;
  }
  if (Array.isArray(payload.data)) return payload.data;
  return [];
}

function uniqueHeaders_(rows) {
  var seen = {};
  var headers = [];
  rows.forEach(function(row) {
    Object.keys(row).forEach(function(key) {
      if (!seen[key]) {
        seen[key] = true;
        headers.push(key);
      }
    });
  });
  return headers;
}

function writeObjectsToSheet_(sheetName, rows, clearSheet) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName(sheetName) || ss.insertSheet(sheetName);
  if (clearSheet !== false) sheet.clearContents();

  if (!rows.length) {
    sheet.getRange(1, 1).setValue('No rows returned');
    return 0;
  }

  var headers = uniqueHeaders_(rows);
  var values = [headers].concat(rows.map(function(row) {
    return headers.map(function(header) {
      var value = row[header];
      return value === undefined || value === null ? '' : value;
    });
  }));

  sheet.getRange(1, 1, values.length, headers.length).setValues(values);
  sheet.setFrozenRows(1);
  return rows.length;
}

function isoDateDaysAgo_(days) {
  var date = new Date();
  date.setDate(date.getDate() - days);
  return Utilities.formatDate(date, Session.getScriptTimeZone(), 'yyyy-MM-dd');
}

function isoDateToday_() {
  return Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyy-MM-dd');
}

2. Clicks import script

Paste this below the shared client, save the project, then run the import function (or use the Hi Energy AI custom menu after reloading the sheet).

/**
 * Import click analytics into Google Sheets.
 * Requires the shared Hi Energy client helpers in this Apps Script project.
 *
 * start_date and end_date are required. Maximum range is 90 days.
 */
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('Hi Energy AI')
    .addItem('Import clicks', 'importHiEnergyClicks')
    .addToUi();
}

function importHiEnergyClicks() {
  var START_DATE = isoDateDaysAgo_(30);
  var END_DATE = isoDateToday_();
  // Admins only: set a publisher id to scope clicks. Non-admins are scoped automatically.
  var PUBLISHER_ID = '';

  var page = 1;
  var perPage = 100;
  var allRows = [];
  var maxPages = 50;

  while (page <= maxPages) {
    var payload = hiEnergyApiGet_('/api/v1/clicks', {
      start_date: START_DATE,
      end_date: END_DATE,
      publisher_id: PUBLISHER_ID,
      page: page,
      per_page: perPage,
      include_total: false
    });

    var records = Array.isArray(payload.data) ? payload.data : [];
    if (!records.length) break;

    records.forEach(function(row) {
      var flat = {};
      Object.keys(row).forEach(function(key) {
        var value = row[key];
        flat[key] = (value !== null && typeof value === 'object') ? JSON.stringify(value) : value;
      });
      allRows.push(flat);
    });

    if (records.length < perPage) break;
    page += 1;
  }

  var count = writeObjectsToSheet_('Clicks', allRows, true);
  SpreadsheetApp.getActiveSpreadsheet().toast('Imported ' + count + ' click rows', 'Hi Energy AI', 5);
}

Useful query parameters

Parameter Purpose
start_date Required ISO date (YYYY-MM-DD). Inclusive range start.
end_date Required ISO date (YYYY-MM-DD). Inclusive range end.
publisher_id Admins can scope to a publisher; other users are auto-scoped.
page / per_page / limit Pagination controls for large click extracts.
include_total Optional total count for reporting UIs.

FAQ

Paste the shared Apps Script client and clicks importer, set HIENERGY_API_KEY, then run importHiEnergyClicks. It calls GET /api/v1/clicks with required start_date and end_date.

The Clicks API allows at most 90 days between start_date and end_date. Split larger history into multiple imports.

Yes. Non-admin users are scoped to their publisher. Admins may optionally pass publisher_id.

Yes. GET /api/v1/clicks requires both dates. The sample defaults to the last 30 days; adjust START_DATE and END_DATE before running.

Clicks responses return flat objects under data (not nested JSON:API attributes), so the importer writes those fields directly as spreadsheet columns.

Yes. This page publishes TechArticle, HowTo, FAQPage, BreadcrumbList, WebSite SearchAction, and related endpoint ItemList structured data for answer engines.
Ask Dex AIIntegration help

If this page feels TLDR, ask Dex AI.

Dex AI speaks your language, and all the other languages you may not. It will write the integration for you with the right endpoint and headers in one plain-English answer.