I know this topic has been discussed before on the forum, but I was just stumped on it for a few hours, so I'm going to post the solution I found here in case anyone else finds themselves in a similar situation in the future (e.g. if you are redirecting participants to an external form in Qualtrics, or if you are tracking participants in a system like SONA and want to automatically mark participants as having "completed" your study in SONA by redirecting them to a SONA confirmation URL).
I need to send participants to an external URL at the end of my oTree app. But, this external URL needs to be dynamic. At the end of the URL, I need to append the participant's bonus amount, and their participant label. So, something like this...
Bonus parameter: bonus=[participant_bonus]
Label parameter: id=[participant_label]
The way I am building the dynamic URL is through the vars_for_template(self): function defined on the class for the last page in my oTree app. E.g.
class LastPage(Page):
def vars_for_template(self):
label= self.player.participant.label
bonus = c(self.player.payoff).to_real_world_currency(self.session)
link = "www.somesurvey.qualtrics.com/?bonus=" + str(bonus) + "&id=" + str(label)
return{'link': link}
Then, on the last page of my app, I use a javascript function to open the external URL in a new tab when the participant clicks the "Next" button. Here's the html for that final page (that DID NOT work)...
{% extends "global/Page.html" %}
{% load staticfiles otree_tags %}
{% block scripts %}
<script>
var link = "{{ link }}"; //this doesn't work
function NewTab() {
window.open(link, "_blank");
}
</script>
{% endblock %}
{% block content %}
<p>Click Next to complete the Payment Survey</p>
<button id="id_submit_button" onclick="NewTab()" class="otree-btn-next btn btn-primary next-button otree-next-button">Next</button>
{% endblock %}
The javascript function sort of works as expected. It sends the participant to the external URL in a new tab. But, I see in the address bar of the new tab that the ampersand character that precedes the participant label parameter in the URL has been replaced with the encoded named entity "&" - as a result, the external site does not recognize that there is a new entity reference ahead of the participant label parameter, and fails to capture that parameter.
In Debug mode, the link variable passed to the DOM appears to be correct. But, when I view the source for the final page of my oTree app, I see the following in the script block...
I didn't see anyone mention this elsewhere on the forum, but apparently Django escapes variables for you when you pass them into the DOM. So, if you want to pass a URL to javascript, you have to make sure that Django doesn't escape the ampersand characters in your URL by using the following syntax: {{ [url_variable_name] | escapejs }}
Here's what that looks like in the present example I started with above...
{% extends "global/Page.html" %}
{% load staticfiles otree_tags %}
{% block scripts %}
<script>
var link = "{{ link | escapejs }}"; //here's where that new syntax comes in
function NewTab() {
window.open(link, "_blank");
}
</script>
{% endblock %}
{% block content %}
<p>Click Next to complete the Payment Survey</p>
<button id="id_submit_button" onclick="NewTab()" class="otree-btn-next btn btn-primary next-button otree-next-button">Next</button>
{% endblock %}
I think this is still relevant if you are trying to use the window.location solution, as opposed to the weird custom button function I'm using here. I couldn't figure out how to get this to work using the
js_vars function, so I'm not sure if the better solution is to just use js_vars, and I'm just doing js_vars wrong. The {{ [variable_name] | escapejs }} syntax works, though, in any case, so I figured I'll leave it here in case anyone needs it.