FreeGoogle Tag Manager recipes

Track Tally Forms submissions in Google Tag Manager with this Free GTM Recipe

A free, tested Google Tag Manager recipe that captures Tally Forms submissions and turns them into a trigger you can use to fire conversions to Google Ads, Google Analytics and more.

Aaron Beashel
Aaron BeashelUpdated July 20267 min read
The Tally recipe tag inside Google Tag Manager

Google Tag Manager is a common way to send conversions to Google Ads, Google Analytics, etc when someone submits a Tally form on your website.

The problem is, it's quite difficult to set up. Tally Forms load inside an embedded iFrame on your site, so Google Tag Manager's built-in form submission trigger doesn't work. This means you're left having to write custom code that listens for Tally's messages, sends an event to the dataLayer, and builds a trigger on top of that.

And unless you're a developer or very experienced with Google Tag Manager, you're going to struggle.

Fortunately though, there is a simple solution.

You can simply install this Tally Forms Conversion Tracking Recipe in your Google Tag Manager account and you'll have everything you need to get basic conversion tracking set up.

What Is a Google Tag Manager Recipe and What's in It?

A recipe is a pre-built bundle of Google Tag Manager assets (a tag, a trigger and two variables) that you import in one go instead of building each piece yourself. You can see all our recipes and how they work in the GTM recipe library.

This recipe detects successful Tally Forms submissions, sends a 'Form Submitted' event to Google Tag Manager, and gives you a Trigger you can use to send conversions to Google Analytics, Google Ads, etc.

Here's exactly what each piece contains:

Custom HTML Tag

Listens for successful Tally Forms submissions and pushes a 'tally_form_submitted' event to the dataLayer. It fires on All Pages, once per event, and this is the code inside it.

The Tag's CodeJavaScript · 72 lines
(function () {
  if (window.__converlyRecipeTally) return;
  window.__converlyRecipeTally = true;
  window.dataLayer = window.dataLayer || [];

  function fireConversion(formId, formName) {
    window.dataLayer.push({
      event: 'tally_form_submitted',
      form_id: formId || '',
      form_name: formName || ''
    });
  }

  function parseMessageData(data) {
    if (!data) return null;
    if (typeof data === 'string') {
      try {
        return JSON.parse(data);
      } catch (e) {
        return null;
      }
    }
    if (typeof data === 'object') return data;
    return null;
  }

  // HTTPS-only, host-anchored so "evil-tally.so.attacker.io" (substring)
  // and "http://tally.so" (scheme downgrade) both fail.
  var TALLY_ORIGIN_PATTERN = /(^|\.)tally\.so$/;

  function isTrustedOrigin(event) {
    if (!event) return false;
    // Reject self-posted messages: Tally never posts from our own window.
    if (event.source === window) return false;
    // Reject messages with no source — a real cross-origin iframe message
    // always carries a source WindowProxy.
    if (!event.source) return false;
    if (!event.origin || typeof event.origin !== 'string') return false;
    var hostMatch = /^https:\/\/([^/]+)/.exec(event.origin);
    if (!hostMatch) return false;
    return TALLY_ORIGIN_PATTERN.test(hostMatch[1]);
  }

  function handleMessage(event) {
    try {
      if (!event || !event.data) return;
      var msg = parseMessageData(event.data);
      if (!msg) return;
      var eventName = msg.event || msg.type;
      if (eventName !== 'Tally.FormSubmitted') return;
      if (!isTrustedOrigin(event)) return;

      // Payload-schema check: a well-formed Tally.FormSubmitted carries a
      // payload object whose `fields` is an array. Without this a malformed
      // (but origin-trusted) message could still fire a phantom conversion.
      var payload = msg.payload || msg.data || msg;
      if (!payload || typeof payload !== 'object' || !Array.isArray(payload.fields)) return;

      // formId/formName are Tally's own form metadata carried directly on
      // the payload — not user-submitted field values — so reading them
      // costs nothing beyond the object property access already needed for
      // the shape check above.
      fireConversion(payload.formId, payload.formName);
    } catch (e) {
      // Never throw back into the page's own message handling.
    }
  }

  if (typeof window !== 'undefined' && window.addEventListener) {
    window.addEventListener('message', handleMessage, false);
  }
})();

Variables

Capture the ID and name of the form that was submitted, ready to reference in any tag. These are their exact settings.

Name

DLV - Tally Form ID

Variable Type

Data Layer Variable

Data Layer Variable Name

form_id

Name

DLV - Tally Form Name

Variable Type

Data Layer Variable

Data Layer Variable Name

form_name

Trigger

Fires when the 'tally_form_submitted' event is received. Use it as the Trigger for any conversion tag. These are its exact settings.

Name

CE - Tally Form Submitted

Trigger Type

Custom Event

Event Name

tally_form_submitted

Download This Recipe

Get the ready-to-import file and upload it into Google Tag Manager. Everything shown above (the tag, the trigger and both variables) comes pre-built inside.

Built from Converly's own Tally detection code

Why It's the Best Recipe Out There

It is built from the same detection code we use in our own conversion tracking product, Converly, just adapted to run inside Google Tag Manager.

Fires only on a successful submission. The code listens for Tally's form submission success event and only fires when it is received. It does not fire on rejected submissions (like if a required field was missing, or the lead enters their email address in an incorrect format, or the submission doesn't pass a spam check).
Verifies the message first. Tally Forms live in an embedded frame that announces submissions to your page, and most public scripts skip the security check, which means any script on the page can fake a conversion. This recipe validates the sender before trusting anything.
Has been extensively tested with the same QA process our own conversion tracking product uses, and has been used to detect thousands of Tally submissions by Converly customers.

How to Use the Tally GTM Recipe

1

Install the Recipe

Download the recipe using the form above, then import it into your Google Tag Manager container. In GTM, head to Admin, choose Import Container, select the downloaded file, and pick the Merge option so it doesn't overwrite anything already in your container. The listener, variables and trigger are added for you automatically.

Importing the recipe container in Google Tag Manager
2

Configure Your Tags

Now that the recipe is installed, you can use it as a Trigger for your conversion tags. Here are two common examples.

Example 1: Google Analytics

Create a GA4 event tag and set Trigger it fires on to be 'CE - Tally Form Submitted' (which is the Trigger the recipe gives you). Every Tally submission now sends an event to Google Analytics.

A GA4 event tag using the recipe's trigger

Example 2: Google Ads

Add your Google Ads conversion tag and fire it on the Trigger the recipe gives you (called CE - Tally Form Submitted) to send conversions to Google Ads whenever a Tally Form is submitted.

A Google Ads conversion tag using the recipe's trigger

What This Enables You to Do (and What It Doesn't)

This recipe fires an event in Google Tag Manager whenever a successful Tally Forms submission is detected. You can use that as a trigger to send conversions to Google Ads, Google Analytics and other tags.

What it does

Sends an Event to GTM

Detects successful Tally Forms submissions and pushes an event called 'tally_form_submitted' into your dataLayer automatically.

Tells You Which Form Fired

Captures the ID and name of the form that was submitted, so a site with several forms can fire different tags for different forms.

Creates a Trigger in GTM

Gives you a 'Trigger' in Google Tag Manager which you can use as the trigger for any of your conversion tags.

What it doesn't do

Doesn't send the conversion server-side

The conversion is sent to Google Tag Manager (and then onto Google Ads, Google Analytics, etc) through the visitor's browser, so ad blockers can stop the tag loading and browser privacy restrictions can limit tracking to as little as a day.

No Click IDs or Identifiers

It does not capture the Google click ID, Facebook click ID, Meta pixel cookies, IP address or user agent, which ad platforms need for Enhanced Conversions (Google) or a proper Event Match Quality score (Meta).

No Personal Details

The script only fires an event. It does not capture the lead's name, email or phone number and pass them through to the ad platform (which they need to match a conversion back to a real person and the ad they first clicked).

No Logging or Notifications

You can test it with Tag Assistant when you first set it up, but unless you check every week, you have no way of knowing if it breaks (except 2 weeks later when you see 0 conversions in Google Ads and your budget is being spent like crazy trying to find more conversions)

The Proper Way to Send Conversions to Google Ads, Meta Ads & More

This recipe is fine if you only send events to Google Analytics, which does not accept personal information or IP addresses. But to get a good Event Match Quality (EMQ) score in Meta, or use Enhanced Conversions in Google, you need to send the data server-side, together with the lead's name and email. That is what Converly does.

A Converly workflow sending Tally conversions to ad platforms

Here's why Converly is the best way to send conversions to Google Ads, Meta Ads, ChatGPT Ads, Microsoft Ads, LinkedIn Ads, etc.

Easy to set up

Converly gives you a simple drag-and-drop builder you can use to build a Conversion Flow. Simply select a trigger (like a Tally Form being submitted) and then select your actions (like sending a conversion to Google Ads). No custom code, no complex configuration. You can even connect it to AI tools like Claude or ChatGPT and simply say 'Set up Tally Forms conversion tracking' and everything will be done for you.

Sends Data Server-Side

Instead of sending conversions through the visitor's browser, Converly sends them directly to Google, Meta, etc. servers, so ad blockers and privacy restrictions can't get in the way.

Sends More Data

It captures the lead's name, email and phone plus the Google and Facebook click IDs, IP address and user agent, and sends them with every conversion. That enables Enhanced Conversions in Google Ads, or gives you an Event Match Quality (EMQ) score of 9 or 10 in Meta.

Full Conversion Log & Email Notifications

See every conversion, what was captured, what was sent to each platform and whether it was received. Get email alerts so tracking can't break without you knowing.

Supports Multiple Tools & Destinations

Detects submissions across 100+ form, scheduling and chat tools and sends to 20+ destinations including Google Ads, Meta, ChatGPT, LinkedIn, Microsoft and TikTok. So if you ever add a new tool to your website or start advertising on a new platform, setting up conversion tracking just takes a few clicks.

Provides Free Support

Our team has 20 years of experience in conversion tracking and analytics and is here to help whenever you need it. With Google Tag Manager, you're on your own.

Start Your Free Trial

Start a 14-day free trial and track your conversions the proper way. No code, no complicated configuration.

About the author

Aaron Beashel
Aaron Beashel

Aaron is the founder of Converly. With over 15 years of experience in digital marketing and SaaS, he's passionate about helping businesses track and optimise their ad conversions.

Start your free trial

Easily send conversions to your ad platforms and analytics tools.
No code required.