Prevent duplicate entries on your forms using Serverless

picsoung profile image Nicolas Grenié Originally published at Medium on ・5 min read

“monkey looking at mirror” by Andre Mouton on Unsplash

It’s a recurring question from our customers: how to prevent people from answering a typeform twice?

Until now, we were telling them to discard the duplicates when they were looking at results, but now we may have a stronger solution using our own APIs and a bit of Serverless logic.

I may have a tendency to always try to solve problems using technology, so when my co-workers told me about this duplicate issue, I knew we could do something using our API.

You can check a working prototype here. Try to answer once, and then try again, you should be blocked.

General principle 🗺

For this example, we will prevent a user to fill again a typeform if their email address has already been associated to a previous response.

We will use the native logic jump functionality. If the email is "authorized" we will go to the next question, if not we will go to a statement block saying "sorry, you already filled this form".

You can manually add a list of email addresses, but we want to automate this, right? 😄

For that automation we will use our webhooks. When a new response is submitted, it will trigger a webhook. The webhook will extract the email from the payload, create a new logic block, and update the logic on Typeform using our Create API.

Here is a chart on how it will work:

A gif worths a thousand words

Prepare your typeform 💄

First step of this tutorial is to prepare your typeform to make it work with our integration. If you don’t have yet an email block, add one to your form now like this:

Drag and drop an email block into your form

We also need to add a statement block. This is where we will redirect the user if they already filled the typeform, so come up with a nice message 😁

Add base of logic block ⚖️

Now get into the logic panel, so you can add the logic base of our form. Select the email block, and add a new constraint that will redirect to the statement block if email is equal to test@test.com (you can delete it later). And in all other cases jump to your next question.

On the statement block, add a logic to always redirect to the email block. This is how it should look like:

Logic map for our form

Test it 🏄‍

To make sure the logic works, let’s test it! Go fill your form and use test@test.com in the email block, you should be redirected to the statement block and then back again to the email block.

Does it work? Time to automate it 😜

A bit of code 🤓

We now want to add a small piece of code that will automatically add a new rule in our logic every time someone answers a form for the first time.

To make ease development and deployment we will use AWS Lambda and Serverless Framework, so please make sure you have both have AWS CLI configured and Serverless framework installed before going further.

Then, clone our repo locally on your machine.

git clone https://github.com/picsoung/tf-lambda-limit-one-entry.git
cd tf-lambda-limit-one-entry
npm install

In the folder you will find a serverless.yml file that contains configuration instruction for our function.

If you open it, you will see a few placeholders for some environnement variables we will need.

    handler: handler.addLimitLogic
      FORM_ID: '' # Which form you want to update
      FIELD_ID: '' # Which field
      FIELD_REF: ''
      TF_TOKEN: '' #Typeform API token
      - http: POST addLimitLogic

Get TF_TOKEN value 🔑

You will need to create a Personal API Token for your account.

On Typeform, go to My Account > Personnal Tokens.
Create a new token and copy its value in the serverles.yml file.

Get FORM_ID value 📃

Your can find the vale of FORM_ID by looking at the public URL of your typeform.
It should be of the form https://{username}.typeform.com/to/{form_id}.
Copy form_id to the serverless.yml file.


To get the remaining values, we will make a call in the browser to the following URL: https://api.typeform.com/forms/{form_id} (replace form_id by the value you found earlier).

You should see a JSON file, this is the definition of your typeform, it has all the fields and logic described in a scripted manner.

From this JSON file we will extract the values we are interested in.

FIELD_ID and FIELD_REF correspond to the id and ref properties of the email block.

Find the email block and copy values.

ALREADY_FILLED_FIELD_REF corresponds to the ref property of the statement block. Find the statement block and copy it’s ref value.

All the environment variables in serverless.yml should now have a value.

We are ready to deploy this function to the cloud.

Deploy Serverless function ⏫

Go back to your terminal and run the following command:

sls deploy

This will run a bunch of scripts and at the end it should give your a URL from AWS, in the form of https://{something}.execute-api.{aws_region}.amazonaws.com/{env}/addLimitLogic .

Copy this URL.

Add Webhook to our form 🔗

This are the final steps:

  • Add the URL we created at the previous as a webhook to our form.
  • On your Typeform dashboard, go to the Integrate tab of form and select Webhooks.
  • There, paste the URL and turn on the toggle. The bubble next to Webhooks should now be green.

BOOM! You now have a Typeform connected to a webhook that will add logic blocks automatically!

Rejoice! 😍

Now that everything is setup, let’s try if our integration is working properly.

  1. Fill your form for the first time using an email address.
  2. Once is submitted, go to your Typeform Create interface and check the Logic panel. You should see a new rule.
  3. Try to fill the form again using the same email address, you should now see the message you defined earlier.

Your form is now protected against duplicate entries based on email address!

Going further 🚀

I just wanted to show a simple example so you all have a base to come up with more complex use cases. There are many other things that could be done.

For this example we used email as an unique identifier but, as you may have guessed. it’s easy to find a workaround to fill the form twice. Instead, you can probably use a random id, and pass it as a hidden_field.

Keep in mind that if you use it with email restriction, the limitation will only work after you put it in place. If you want to limit people who already filled the form, it might worth writing a script to extract email from previous responses and create corresponding logic block.

I hope you liked this tutorial, please let me know if anything is broken or unclear, and feel free to suggest ideas for next projects!

Happy Hacking \m/

🎵 Sweet dreams are made by geeks, who are we to ditch a PR? We travel to events and assorted meetups. Everybody is looking for swag.
🎵 Sweet dreams are made by geeks, who are we to ditch a PR? We travel to events and assorted meetups. Everybody is looking for swag.


Editor guide