Get Started Log in
Docs / Typeform and Gravity Forms

Typeform and Gravity Forms

Both need the Sourcream script on the page (Custom HTML sites, WordPress). Pages with a Typeform embed also need it loaded with defer (step 3).

Typeform

Typeform embeds run inside an iframe, so no script on your page can fill their fields directly. Typeform's own hidden fields solve this: the embed passes them into the typeform when it loads, and Sourcream sets them for you.

1. Add hidden fields in Typeform

In the Typeform editor, add hidden fields with exactly these names:

first_source, first_medium, first_campaign, last_source, last_medium, last_campaign, sc_visitor_id

(If you renamed fields under the site's Field names in Sourcream, use your names.)

2. Embed with Typeform's embed code

Use Typeform's standard embed (any of data-tf-live, data-tf-widget, data-tf-popup, data-tf-slider, data-tf-popover or data-tf-sidetab). The Sourcream script finds the embed element and sets its data-tf-hidden attribute to first_source=...,first_medium=...,...,sc_visitor_id=..., which Typeform passes into the form.

If your embed already has a data-tf-hidden attribute (for example to pass UTMs), Sourcream leaves it alone. Remove it, or add the Sourcream names to it yourself with values from Sourcream.read().

Links that open typeforms on typeform.com (not embedded) cannot receive the values.

3. Load Sourcream with defer on pages with an embed

Typeform reads data-tf-hidden once, as soon as the page's HTML has finished loading (the DOMContentLoaded event), and ignores any later change. The standard Sourcream tag loads with async, which lets it run after that moment, for example when the script is not cached yet. The embed then starts without the values, and the lead arrives in Sourcream as (direct). Putting the tag in the <head> does not change this.

On every page with a Typeform embed, load the Sourcream script with defer instead of async, in the <head>:

<script src="https://cdn.sourcream.ai/t/YOUR_SITE_KEY.js" defer></script>

A defer script still does not block rendering, and browsers always run it before DOMContentLoaded. The Sourcream script sets data-tf-hidden as soon as it runs, so the values are in place when Typeform reads them. The same applies to the first-party proxy tag: <script src="/_sc/t/YOUR_SITE_KEY.js" defer></script>.

Leave Typeform's own embed.js tag as Typeform supplies it, a plain <script> without async or defer. Typeform then waits for DOMContentLoaded, which comes after Sourcream. If a plugin or page builder adds embed.js with async, or with defer ahead of the Sourcream tag, Typeform can read the attribute before Sourcream has set it.

  • WordPress plugin. The plugin adds the script with async. To switch it to defer, add this to a child theme's functions.php or a code snippets plugin:

    add_action( 'wp_enqueue_scripts', function () {
        wp_script_add_data( 'sourcream', 'strategy', 'defer' );
    }, 20 );
    

    With the script tag in the theme instead (WordPress, option B), write defer in place of async in the tag.

  • Google Tag Manager. A tag that GTM adds cannot be guaranteed to run before Typeform reads the attribute. On pages with a Typeform embed, put the Sourcream tag in the page itself.

  • Consent. With consent mode set to Required or Google Consent Mode, Typeform gets the values Sourcream has at the moment Typeform reads them. If the visitor's consent is not known by then, that is this visit only (first touch equals last touch) and an empty visitor ID, and consent given later on the page does not reach the open embed. For a returning visitor who already accepted, make the answer available before the page finishes loading: set window.SourcreamConsent = true before the Sourcream tag, or have the banner push its Consent Mode update from a script that runs before DOMContentLoaded (Consent).

  • Embeds created in your own JavaScript (Typeform's createWidget, createPopup and similar) have no data-tf-hidden attribute for Sourcream to set. Create them once the Sourcream script has run and pass the values in the embed's hidden option. With the Sourcream tag loaded with defer, a DOMContentLoaded handler is late enough:

    <div id="contact-typeform"></div>
    <script src="//embed.typeform.com/next/embed.js"></script>
    <script>
      document.addEventListener('DOMContentLoaded', function () {
        var v = window.Sourcream ? Sourcream.read() : { first: {}, last: {}, visitorId: '' };
        window.tf.createWidget('YOUR_FORM_ID', {
          container: document.getElementById('contact-typeform'),
          hidden: {
            first_source: v.first.source, first_medium: v.first.medium, first_campaign: v.first.campaign,
            last_source: v.last.source, last_medium: v.last.medium, last_campaign: v.last.campaign,
            sc_visitor_id: v.visitorId
          }
        });
      });
    </script>
    

    Do not wait for Sourcream.ready() here: with a consent mode it only calls back after consent, so the form would not appear for visitors who have not chosen yet.

4. Get the response into Sourcream

Typeform submissions happen inside the iframe, so the Sourcream script does not see them. Send them to Sourcream with Typeform's webhook:

  1. In Sourcream, copy the site's intake URL (Sites, your site, Webhook intake; shown once, rotate to see a new one).
  2. In Typeform, open the form's Connect, Webhooks, add the intake URL and turn it on.

Sourcream reads the hidden fields from form_response.hidden, finds the email among the answers, links the lead to the visitor through sc_visitor_id and de-duplicates on Typeform's event_id. The lead then goes to your connected CRM like any other. Typeform's native HubSpot or Salesforce integrations can also map the hidden fields straight into CRM fields if you prefer.

Gravity Forms

Gravity Forms names its inputs by field number (input_4), so Sourcream cannot recognise them by name. Use CSS classes instead.

1. Add hidden fields

For each value, add a Hidden field to the form and set Appearance, Custom CSS Class:

Field label (your choice) Custom CSS Class
First source sc-first_source
First medium sc-first_medium
First campaign sc-first_campaign
Last source sc-last_source
Last medium sc-last_medium
Last campaign sc-last_campaign
Sourcream visitor ID sc-sc_visitor_id

Gravity Forms puts the class on the field's wrapper (.gfield), and the Sourcream script fills the input inside it. If your version does not offer the class on Hidden fields, use a Single Line Text field with Advanced, Visibility set to Hidden and the same class. The values then appear in each entry, in notification emails (merge tags) and in Gravity Forms add-ons such as HubSpot, Salesforce or Zapier.

Gravity Forms' AJAX and multi page forms are fine: the script fills forms rendered after page load too.

2. Lead capture

Each submission is reported to Sourcream from the browser. For server side capture as well, use the Gravity Forms Webhooks add-on:

  1. Add a webhook feed with your Sourcream intake URL, method POST, format JSON.
  2. Request Body: Select Fields, and add keys sc_visitor_id, email, name, phone, company, the six hidden field keys (first_source ...), each mapped to its field, and event_id mapped to the entry ID.

Choosing "All Fields" sends Gravity Forms' field numbers as keys, which Sourcream cannot match; use Select Fields. The browser report and the webhook for the same submission are merged into one lead.

Check it

Submit a test with ?utm_source=test&utm_medium=test&utm_campaign=forms on the page address, then check the Typeform response or Gravity Forms entry for the hidden values and Leads in Sourcream for the lead.

Questions: [email protected]

Stuck on an install? Email [email protected] with your site address and what you are seeing, and we will help you get it working.