how to setup a google sheets that syncs your aliases & domains to improvMX

Tips

This is a blog explaining how to sync ImprovMX domains and aliases directly from Google Sheets. Each row edit triggers a Google Apps Script that creates or updates the domain, alias, and wildcard alias using the ImprovMX API.

Sheet layout

Create a Google Sheet with these columns:

Google Sheets layout with columns for domain, alias, forward address, and status

What the script does

On every row edit:

  • Creates the domain if it doesn't exist
  • Creates or updates the alias
  • Creates or updates the wildcard (*) alias
  • Writes the result to the Status column

Setup

  1. Open the sheet
  2. Go to Extensions → Apps Script
  3. Paste the script below
  4. Replace YOUR_API_KEY_HERE with the ImprovMX API key:
ImprovMX API key location

Now you just save and exit.

Google Apps Script

const BASE_URL = "https://api.improvmx.com/v3";
const API_KEY = "YOUR_API_KEY_HERE";
const SHEET_NAME = "Sheet1";
const START_ROW = 4;

function onEdit(e) {
  if (!e) return;
  const sheet = e.source.getActiveSheet();
  if (sheet.getName() !== SHEET_NAME) return;
  processRow(sheet, e.range.getRow());
}

function processRow(sheet, row) {
  if (row < START_ROW) return;
  const [domain, alias, forwardTo, status] =
    sheet.getRange(row, 1, 1, 4).getValues()[0];
  if (!domain || !alias || !forwardTo) {
    sheet.getRange(row, 4).setValue("Missing data");
    return;
  }
  const done = `Synced: ${domain} | ${alias} → ${forwardTo}`;
  if (status === done) return;
  try {
    ensureDomain(domain);
    upsertAlias(domain, alias, forwardTo);
    upsertAlias(domain, "*", forwardTo);
    sheet.getRange(row, 4).setValue(done);
  } catch (err) {
    sheet.getRange(row, 4).setValue(`Error: ${err.message}`);
  }
}

function ensureDomain(domain) {
  const res = api("post", "/domains", { domain: domain.trim() });
  if (
    res.code === 200 ||
    res.code === 201 ||
    res.body.includes("already registered")
  ) return;
  throw new Error(res.body);
}

function upsertAlias(domain, alias, forwardTo) {
  const clean = alias.includes("@") ? alias.split("@")[0].trim() : alias.trim();
  const path = `/domains/${encodeURIComponent(domain)}/aliases/${encodeURIComponent(clean)}`;
  const res = api("put", path, { forward: forwardTo });
  if (res.code === 200 || res.code === 201) return;
  throw new Error(res.body);
}

function api(method, path, payload) {
  const r = UrlFetchApp.fetch(BASE_URL + path, {
    method,
    contentType: "application/json",
    payload: JSON.stringify(payload),
    headers: { Authorization: "Basic api:" + API_KEY },
    muteHttpExceptions: true
  });
  return { code: r.getResponseCode(), body: r.getContentText() };
}

Enable the trigger

In Apps Script, open Triggers:

Apps Script Triggers menu

Add a trigger:

Apps Script Triggers page with Add Trigger button
  1. Function: onEdit
  2. Event type: On edit
Trigger configuration dialog

Then save and authorize the script.

Result

Editing a row keeps ImprovMX domains and aliases in sync with the spreadsheet. The sheet becomes the source of truth.

Matthew Tse

Matthew Tse

Owner and CEO of ImprovMX