Google Apps Script allows scripts to be triggered by a variety of events; see here.
I'd like to update the tag on an email (in Gmail) when the user marks a task completed (in Google Tasks) but there doesn't seem to be a trigger for this.
However, Zapier is able to trigger on these events somehow: supported triggers
So it seems like this trigger must exist.
Is there a way to do this other than using Zapier?
Unfortunately Zapier (in addition to costing money) only allows you to add tags to Gmail messages, not remove them -- so one can't (for instance) change a message tag from [uncompleted-task] to [completed-task].
As of this writing (2018-05-15), Google Apps Script does not support a trigger to track a task's status.
I suspect that Zapier is polling the status of the task via the Task API; ie. periodically checking the status property of the task and firing an event once the status changes to complete.
You can do the same (with time-based triggers) using the Task API as an Advanced Service in GAS: