1

I need to send a simple (one-off) survey to users and capture their answer in the most unobstructive way. It's one question with a yes/no answer.

Setting up mailchimp(or other service) seems overkill, so I figured I can just use craft.

Would there be any downsides/potential problems doing it this way.

  1. I create a new section and import (with feedme) each email as an entry, I also assign a unique id to each email. enter image description here

  2. Then, I would send an email with yes / no buttons that have a link with the answer as a query string, like this https://www.domain.com/survey?userid=456&answer=no or

    https://www.domain.com/survey?userid=456&answer=yes

  3. The entry template has this code that updates the answer field upon visiting the page using the configure function.

{# set the custom user id from the querystring #}
{% set userId = craft.app.request.getParam('userid') %}

{# set the answer from the querystring #}
{% set answer = craft.app.request.getParam('answer') %}
    
{% if userId is not null %}
  {% set entry = craft.entries
      .section('survey')
      .surveyUserId(userId)
      .one() %}
    
    {# Check if the answer field is empty #}
    {% if entry.surveyAnswer is empty %}
    
      {% if answer == 'yes' %}
        {% do configure(entry, { surveyAnswer: 'Yes' }) %}
        {% do craft.app.elements.saveElement(entry) %}
      {% endif %}
    
      {% if answer == 'no' %}
        {% do configure(entry, { surveyAnswer: 'No' }) %}
        {% do craft.app.elements.saveElement(entry) %}
      {% endif %}
                        
    {% else %}
      It seems you've already submitted your answer.
    {% endif %}
    
{% else %}
    No user id defined
{% endif %}

1 Answer 1

1

Very creative!

You probably already noticed that since you have no means of authentication, a malicious user could set everyone else's answer to their preferred answer just by trying out every userId in the URL (a process that could be automated very easily with wget).

To give at least a little bit of protection you could ask them to fill in their email address, and on submit it checks to see if it matches the one you're expecting.

If you want to do it without the effort of a manual form submission you could include a hashed version of their email address as another URL parameter, and then check that it matches the hashed version you're expecting in the template. See encenc Twig filter for example: https://craftcms.com/docs/3.x/dev/filters.html#encenc

A couple of other warnings here too:

  1. You're basically opening up public write-access to your database here. Your conditional checks in the template mitigate the impact of this at the moment (the DB writes only happen if a user ID exists and with no previously selected answer), so for now at least that's ok, but if you make any changes/additions you need to be careful that you don't accidentally make it so that someone can write a script that infinitely writes to your DB. (You could also add a conditional check that entry exists after attempting to fetch it).

  2. When saving confidential data into entries, be careful not to accidentally expose that data in e.g., public sitemaps or internal keyword searches etc. Also be sure to no-index the page so it doesn't get hit by search bots.

1
  • Thanks James! Very insightful remarks. I've implemented your suggestions to increase security. Even installed a fresh craft instance on a subdomain with no public facing pages to separate survey data from the actual site content. Commented Jun 10, 2022 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.