Using Typeform with Anvil

Hello!

I am relatively new to both Anvil and Python, so hoping I am not wasting anyone’s time.

Looking for some help using Anvil’s Email Service to send emails with a Typeform link, then read the responses of the Typeform submission and store them in my Anvil app. Would this be possible?

Reference material I am reading through:
https://developer.typeform.com/responses/
https://developer.typeform.com/responses/reference/retrieve-responses/

Any help or guidance pointing me in the right direction would be much appreciated!

1 Like

Hi Chesney, and welcome to the forum!

It’s definitely possible, and the good news is that it’s quite straightforward to do so :slight_smile:

Here’s a clone link for an app I just pulled together to demonstrate how it might work:

https://anvil.works/build#clone:GZR75BB7BFUBJB6O=I37PNFX57SLKM6AQ3QPIIXUU

I defined two server functions in my ServerModule, one that sends an email with the typeform link, and another that requests data from the typeform api.

The two Buttons in the UI trigger each of these server functions.

Since the typeform api requires you to send your personal access token as a header in the api request, I stored an ecrypted version of my personal token in my app using Anvil’s App Secrets service. I can then access my personal token in my server modules using anvil.secrets.get_secret('typeform_key')

At the moment, I’m just displaying the data returned from the api in a label - I’ll leave you to work through the JSON response and display the data in a more meaningful way.

Give it a go and let me know how you get on!

3 Likes

Thank you so much Bridget! I am going to work on this today and let you know how it goes. Again, appreciate the thoughtful and detailed response :slight_smile:

You’re very welcome!

I also just spotted that Typeform provide a Webhooks API which gives you access to new Typeform responses in real-time.

All you need to do is create a simple HTTP API which can process each response as it comes in. One way is to store the JSON response as a simple object in a Data Table. This function would create an endpoint available at: https://<your-app-id>.anvil.app/_/api/new-response, and store the JSON object in a Data Table called ‘responses’:

@anvil.server.http_endpoint('/new-response')
def display_response():
  # store new form response in your data table 'responses' as a json object
  app_tables.responses.add_row(response=request.body_json)

Then, using the Typeform Webhook API, you can create a webhook which will call this endpoint each time a new response is received:

@anvil.server.callable
def create_webhook():
  anvil.http.request('https://api.typeform.com/forms/<your-form-id>/webhooks/<name-for-your-webhook>',
    method="PUT",
    headers={
      "authorization": "bearer {}".format(anvil.secrets.get_secret('typeform_key')),
                     },
    json=True,
    # 'enabled:true' sends new form responses to the webhook immediately
    data= {"url": "https://<your-app-id>.anvil.app/_/api/new-response", "enabled":True})

You have a number of options for displaying the response data once it’s stored in your data table. If you want to check for new data periodically and update your UI to show the new data, you could simply add a timer component to your Form. Then, each time the timer ‘ticks’, you could get data from your Data Table and display it in a Data Grid in your UI, like this:

  def timer_1_tick(self, **event_args):
    """This method is called Every [interval] seconds. Does not trigger if [interval] is 0."""
    response_data = app_tables.responses.search()
    # format the JSON data
    formatted_data = [{'date' : x['response']['form_response']['landed_at'][0:10],
                       'a_1' : x['response']['form_response']['answers'][0]['number'],
                       'a_2' : x['response']['form_response']['answers'][1]['choice']['label'],
                       'a_3' : x['response']['form_response']['answers'][2]['number']
                                    } for x in response_data]
    self.repeating_panel_1.items = formatted_data

Here’s the clone link if you want to see how it all pieces together:

https://anvil.works/build#clone:7YMN3XWWYIAZLEGK=KTNNO4SH6WYCKKO23TNQY7TI

You’ll need to add a Typeform key to app secrets to get it working but if you take the survey here, the data will be added to the data grid in your UI :slight_smile:

Let me know if you have any questions!

3 Likes

Hi, I am trying to link a button on my website to directly open a Typeform URL, for example the link: https://.typeform.com/to/. I know about link component, but how do I make the button work as a link component?

I dont want to send an email with the link.

How do I do that?

Would it be easier to use a Link component directly? I.e., instead of the button?

No, that won’t work. Link is just a text with an underline.

I am trying to create a website with buttons as Call to Action.

How will buttons work in anvil webapps then, if there is no provision for a button to be used for navigation?

Maybe this will work?

https://anvil.works/build#clone:ZVH4WQ45AKUBQCVJ=TJWYWYTEF24D5GNXAOQ5IJT2

I imported the webbrowser library and used webbrowser.open() to open a webpage.

1 Like

Thank you, that worked!

1 Like