MMK Hub
Tips

Tips & How-To

Turn a Google Form Into Asana Tasks (Without Copy-Paste)

Desk flat-lay with laptop form mock, sticky-note checkmark, phone task list silhouette.

Someone fills a public Google Form — and an Asana task appears automatically. Plain steps with Google Apps Script for freelancers and small teams (no paid connector required).

You set up a Google Form so people can request help. The responses land in a spreadsheet. Then someone — often you — copies each row into Asana by hand. That works for five submissions a week. At fifty, it becomes a second job.

There is a free middle path: when the form is submitted, a small Google Apps Script can call the Asana Tasks API and create a task for you. No paid “connector” product required. This walkthrough uses a made-up Volunteer Support Desk form so you can copy the pattern without tying it to any real workplace.

MMKHub is informational only. We are not a Google or Asana partner, and we do not set up automation for hire. Treat the code below as a teaching sketch — replace every fake ID and token with your own, and keep secrets out of the form itself.

မြန်မာအကျဉ်းချုပ်

Google Form တင်လိုက်တာနဲ့ Asana မှာ task အလိုအလျောက် ပေါ်အောင် Google Apps Script သုံးနိုင်ပါတယ်။ ဒီဆောင်းပါးက ဥပမာအနေနဲ့ “Volunteer Support Desk” လို့ခေါ်တဲ့ စိတ်ကူးယဉ် form (နာမည်၊ အီးမေးလ်၊ အမျိုးအစား၊ ဦးစားပေး၊ ဖော်ပြချက်) နဲ့ ရှင်းပြထားပါတယ်။ API token ကို form ထဲမထည့်ပါနဲ့ — Script Properties ထဲသိမ်းပါ။ အရေးကြီးကိုယ်ရေးအချက်အလက်တွေ မကောက်သင့်ရင် form ကို လူသိလူသိမဖွင့်ပါနဲ့။ MMKHub က သတင်းအချက်အလက်သာ — vendor မဟုတ်ပါ။

What you will build

A public (or limited) Google Form. On each submit:

  1. Apps Script reads the answers from the form response.
  2. It picks an Asana project from a simple category map (Website → one project, Account → another).
  3. It creates a task with a clear title and a short description that includes the requester’s email and preferred contact time.
  4. Optionally, you can later add a comment on that task when the volunteer team replies — still from script, still without pasting rows.

Useful official starting points (open in a new tab when you build):

Step 1 — Invent a clean form (example fields)

Create a Google Form. For this tutorial, name it something neutral like Volunteer Support Desk. Suggested questions:

Question title (exact wording helps the script) Type Example choices
Requester name Short answer —
Email Short answer (email validation on) —
Category Multiple choice Website · Account · Other
Priority Multiple choice Normal · Urgent
Short description Paragraph —
Preferred contact time Short answer e.g. evenings after 7 p.m.

Keep titles stable. If you rename “Category” to “Topic” later, update the script to match — the sketch looks up answers by question title.

Link a response spreadsheet if you want a backup archive. The automation below can run from the form-bound script (Extensions → Apps Script on the form) or from the spreadsheet’s on-form-submit trigger. Form-bound is enough for this pattern.

Step 2 — Sketch the Asana side

In Asana, create three ordinary projects in a workspace you control, for example:

  • Website fixes
  • Account help
  • General requests

Copy each project’s GID from the project URL (the long number). You will also need your workspace GID (from Asana developer settings or the API explorer). For a personal or small-team setup, a Personal Access Token (PAT) is the usual auth for a simple script — create it in Asana’s developer console, give it a clear label like “form-to-tasks-volunteer-desk”, and treat it like a password.

Never put the PAT in a form question, in the form description, or in a public GitHub gist. Store it in Apps Script Script Properties (Project Settings → Script properties), e.g. key ASANA_PAT.

Step 3 — Apps Script sketch (fake IDs on purpose)

In the form’s Apps Script editor, paste something in this shape. Every gid_… value and the property name are placeholders — swap them for yours.

/**
 * Volunteer Support Desk → Asana (TEACHING SKETCH)
 * Fake GIDs and field titles — replace before use.
 * Store the real PAT in Script Properties as ASANA_PAT.
 */

var PROJECT_BY_CATEGORY = {
  'Website': 'gid_project_website_fixes_0001',
  'Account': 'gid_project_account_help_0002',
  'Other':   'gid_project_general_requests_0003'
};

var WORKSPACE_GID = 'gid_workspace_example_9999';

function onFormSubmit(e) {
  var named = e.namedValues; // spreadsheet-linked trigger style
  // If you use a form-bound installable trigger with e.response instead,
  // read answers via e.response.getItemResponses() and map by item title.

  var name     = (named['Requester name'] || [''])[0];
  var email    = (named['Email'] || [''])[0];
  var category = (named['Category'] || ['Other'])[0];
  var priority = (named['Priority'] || ['Normal'])[0];
  var detail   = (named['Short description'] || [''])[0];
  var when     = (named['Preferred contact time'] || [''])[0];

  var projectGid = PROJECT_BY_CATEGORY[category] || PROJECT_BY_CATEGORY['Other'];
  var taskName = '[' + priority + '] ' + category + ' — ' + name;

  var notes =
    '<body><b>From:</b> ' + escapeHtml_(name) +
    ' &lt;' + escapeHtml_(email) + '&gt;<br/>' +
    '<b>Preferred contact time:</b> ' + escapeHtml_(when) + '<br/><br/>' +
    escapeHtml_(detail) +
    '</body>';

  var pat = PropertiesService.getScriptProperties().getProperty('ASANA_PAT');
  if (!pat) {
    throw new Error('Missing ASANA_PAT in Script Properties');
  }

  var payload = {
    data: {
      name: taskName,
      workspace: WORKSPACE_GID,
      projects: [projectGid],
      html_notes: notes
    }
  };

  var resp = UrlFetchApp.fetch('https://app.asana.com/api/1.0/tasks', {
    method: 'post',
    contentType: 'application/json',
    headers: { Authorization: 'Bearer ' + pat },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  });

  if (resp.getResponseCode() >= 300) {
    console.error(resp.getContentText());
    throw new Error('Asana create task failed: HTTP ' + resp.getResponseCode());
  }
}

function escapeHtml_(s) {
  return String(s)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;');
}

Two trigger styles exist in Google’s docs:

  • Spreadsheet “On form submit” — often easiest; e.namedValues keys match the question titles in the linked sheet.
  • Form-bound installable trigger — ScriptApp.newTrigger('onFormSubmit').forForm(FormApp.getActiveForm()).onFormSubmit().create(); then read e.response.getItemResponses().

Simple onFormSubmit function names do not always fire by magic on a form — create the installable trigger from the Triggers (clock) panel and run the function once by hand so Google can ask you to authorize Forms + external URL fetch.

Step 4 — Test with a dummy submission

  1. Save the script. Put a throwaway PAT in Script Properties (you can revoke it after testing).
  2. Submit the form yourself: Category = Website, Priority = Urgent, short nonsense description.
  3. Open the Website fixes project in Asana. You should see a task titled like [Urgent] Website — Aung Test.
  4. Check Executions in Apps Script if nothing appears — HTTP 401 usually means a bad or revoked PAT; 404 often means a wrong project or workspace GID.

Optional — comment back on the same task later

Once create-task works, the JSON response includes the new task GID. You can store that GID in the spreadsheet row (append a column from the script) and later call Asana’s add-comment endpoint when a volunteer marks “we replied by email.” That second hop is optional; many small teams stop at “form creates the task” and handle replies inside Asana’s UI.

Safety notes (please read)

  • Secrets stay in Script Properties (or a secret manager) — not in form fields, not in task titles, not in public repos.
  • Public forms collect whatever strangers type. If you need ID numbers, passwords, or payment details, do not put those questions on a wide-open form. Use a limited share link, a login wall, or a proper help-desk tool.
  • A PAT acts as the Asana user who created it. Anyone who steals it can act as that user. Rotate it if a laptop is lost; prefer a dedicated bot-style Asana seat when your plan allows.
  • Rate limits and errors happen. Log failures; do not silently drop Urgent requests.
  • This is a pattern, not a product. Google and Asana change APIs and permission screens over time — re-check their current docs before you rely on the sketch in production.

Who this is for

Freelancers abroad running a small community inbox, student clubs, church or alumni volunteer desks, indie product waitlists — anyone already living in Google Forms + Asana who is tired of the spreadsheet shuffle. If your volume is huge or you need SLAs, look at dedicated help-desk software; the script path is the lightweight option.

More practical guides live in the MMKHub how-to archive. MMKHub stays informational: we do not sell connectors, hold your tokens, or operate as an agency.

Bottom line

Form submit → installable Apps Script trigger → POST /tasks to Asana with a category→project map. One afternoon of careful setup can retire years of copy-paste — as long as the PAT stays private and the form only asks for what you are willing to receive from the internet.

Sources for the pattern: Google Apps Script triggers / TriggerBuilder documentation; Asana Tasks API “create a task.” Example field names and project GIDs in this article are fictional.

Back to all lessons