Welcome to the LimeSurvey Community Forum

Ask the community, share ideas, and connect with other LimeSurvey users!

Overview page for respondents with a list of surveys they are invited to

  • socius
  • socius's Avatar Topic Author
  • Offline
  • Premium Member
  • Premium Member
More
6 years 4 months ago #160781 by socius
Dear all,

I'm looking for a way to build an overview page that lists surveys my respondents are invited for, a respondent-side dashboard so to say. The intention is that respondents easily can see their current state (how many surveys completed yet, etc.) in a case where they are invited to participate in a series of surveys.

The idea is:
  • I have a number of respondents that are invited to participate in about say 10 different surveys.
  • I'd like to create an overview page for the respondents that lists these surveys and contains the links and some further information.
  • The token tables of the surveys are identical concering Email-Adresses and tokens (i.e. respondents have the same token in all of these surveys)
  • This overviewpage should be a survey itself - since that makes it easy to send Invitations to this overview

The overview page should contain a table with the following information for each survey:

Survey1: Topic (manually entered) | Survey description (ideally linked to survey) | Median duration (calculated over all previous respondents of the survey) | Date of Invitation/Date started/Date of last Action | Started? (Y/N)/Completed? (Y/N) | Link to Survey1

(same for Survey2, etc.)
...


To build this overview page I would have to get information from
  • the surveys (survey descriptions)
  • the token table (Date of Invitation/Completed Y/N)
  • from the survey results (Date started and/or Started? (Y/N) / Date of last Action)
  • and the time data calculate the median time from the interviewtime Variable of all previous respondents

Is this possible? Which of these informations can I use in this overview (that is itself a survey)? And how? (via combination of SID and placeholders? - That would be too easy, right? ;-)

I'm thankful for all ideas and hints!

Thanks for your time!
Best,
G

PS: I use LS 2.6.4 LTS from the github repository.


Remark: I first thought that @limeAJ ( www.limesurvey.org/forum/can-i-do-this-w...oard-possible#157523 ) wanted to achieve something similar, but I think this here is different enough from what was discussed there (that's why the new thread).
The topic has been locked.
More
6 years 3 months ago #160831 by cairomckenzie
To execute a dashboard-esque, I have created a “landing page” survey, which contains would contain the information about the various surveys one would want to have their tokenized respondents complete. The following conditions must exist in order for this workaround to function:
  1. Surveys must be completed one after the other (the respondent won’t be able to pick and choose what order they’ll complete). I think that this can be adjusted. But it’ll have to happen in the jQuery source code of one of the question. So if you don’t know jQuery, you might have a hard time adjusting this condition.
  2. All surveys MUST be tokenized, and NOT repeatable (1 time use, token can’t be used to submit multiple responses)

I've included some limesurvey structures that you can import and test out. They will work as inactive surveys, but for full functionality, you must activate all three survey's (and follow the instructions below to adjust for your setup).

Overview of Solution:
The solution essentially utilizes a ‘Parent Survey’, which is the survey that you use to send out invitations to respondents, and where respondents start from anytime they want to continue along with their surveys. The ‘Parent Survey’ provides links to many ‘Child Surveys’. These ‘Child Surveys’ utilize the End URL functionality to send the user back to the ‘Parent Survey’ upon completion of the specific ‘Child Survey’. In order to achieve a few processes, we use the Panel Integration functionality to pass thru some data from the Parent to the Child, and then back again.

What does the process look like?
Essentially, the Parent Survey will present with a list of surveys that the participant must complete. If the participant hasn’t completed any listed surveys, the first survey on the list will contain a token link to that specific survey. All remaining survey’s will text requesting the participant to complete the previous survey first before moving on. When the participant clicks on their survey link, the Parent Survey sends two pieces of information to the Child Survey: 1)The id of the specific subquestion related to the Child Survey that the participant just clicked on and 2)The id of the Parent Survey. The reason for the first piece of information is so that the Child Survey knows which question of the Parent Survey to call “Complete”. The reason for the second piece of information is to allow the Limesurvey developer to quickly set up dashboards. Otherwise you would have to hard code the Parent Survey ID in EACH of the Child Surveys, and as developers, it is sometimes better to be lazy. ;)

The participant will then be sent to the Child Survey using the same token that they had on the Parent Survey. Once the Child Survey has been ‘Submitted’, the user is AUTOMATICALLY redirected to the Parent Survey. The Child survey sends two pieces of information back to the Parent survey: 1) The date of the submission of the Child Survey and 2)The question on the Parent Survey that contains the status for that Child Survey.

Upon arriving on the Parent Survey page, the Parent Survey puts the date of completion into the answer field of the Child Survey status. And then redisplays the survey list. The first survey will now show the completion date of the survey that was just completed, and the next survey’s link will become available. This goes on for each survey until all are complete. At which point the Participant may click submit on the Parent Survey, and the whole process is complete. See below for a detailed explanation about how to carry it out.

The Parent Survey
To setup the Parent survey, we only need to create two questions. The first question, named surveyStatus, is of the ‘Multiple short text’ type. Each subquestion of this question should contain the id of the survey you wish to link to as the ‘code’ and the name (or any other info you wish to have stored) in the ‘Subquestion’

So, for example: say we have a separate survey we wish for the participant to take. The name of the survey is ‘Survey 1’. That survey’s ID number is 823115. We would add a subquestion to the question surveyStatus. I've included a picture in the attachments.

After saving this question, we would move on to create the second question of the Parent Survey, called surveyTable . This question will be of the type ‘Text display’. Within the source code of this question. We paste the following monstrosity of code. In essence, it uses the information provided in surveyStatus to create a table of survey names, links to the external survey, and the status of completion for each of those surveys. You MUST adjust the code below for the var surveyServer and replace it with the address for your server, up to, but not including, ‘/index.php/’
Code:
<!-- Create a div within the question to wrap the table that we use to display the links/survey data -->
<div id="survey-table"> </div>
Code:
<script>
    //define the survey server address below
    var surveyServer = "http:<YOUR_SERVER_ADDRESS> [attachment=11214]Dashboard_Example.zip[/attachment] [attachment=11214]Dashboard_Example.zip[/attachment]/index.php/";
    //grab the survey names, survey completion status, and survey numbers from LS
  var surveyNames = "{list(that.surveyStatus.question)}";
    var surveyAnsArr = new Array();
    //we iterate through the listed surveys to gather their responses from the surveyStatus subquestions(the surveys)
    //and store them in an array
    if(!({count(that.surveyStatus.valueNAOK)}==0)){
      surveyAnsArr = "{list(that.surveyStatus)}".split(",");   
       };
    //get the qids for each surveyStatus subquestion(survey)
    var surveyQidArr = "{that.surveyStatus.qid}".split(",");
    //Survey qid's for subquestions aren't all that easy to tease out, so we get the QID here, and add the LS  'X' delimeter to it for future use
    var surveyQid = "X" + surveyQidArr[0];
    //Then we get the FULL subquestion id (the qid + the subquestion id)
    var surveySGQAs = "{list(that.surveyStatus.sgqa)}".split(",");
    //Then we get the survey names that we grabbed above from the surveyStatus.question for use in the table we'll create later
    var namesArr = surveyNames.split(",");
    var numberArr = new Array();
    //have to break out the survey number from the QID....
     for(i=0;i<surveySGQAs.length;i++){
            sgqa = surveySGQAs[i];
          //useing the qid, we tease out what the subquestion id is. Since the survey id is used as the subquestion id, we now have that for use later...
            numberArr.push(sgqa.substring(sgqa.lastIndexOf(surveyQid)+surveyQid.length));
       };
 
  var lastCompleted = false;
  var startNew = true;
  var status = "";
 
    $(document).ready(function() { 
 //this section creates a table with names and links in a way that LS just can't provide easily. THis way we can control the look/feel a little better.
  var table = $("#survey-table");
  addHtml = "<table><tr><th>Name</th><th>Status</th></tr>";
    //create the table and relevant content using the variables above
    //We use the names array we created above to create each row of the table that will display the survey name, the survey link, and the status for the participant of that survey
  for(i=0;i<namesArr.length;i++){
    addHtml += "<tr>";
    //if there are no answers available, LS returns nothing, so answer array should be 0 length
    addHtml += '<td>'+namesArr[i]+'</td>';
    //I go through a series of if statements to determine what to included in the next cell of the table 
    //I apologize in advance for any and all coding faux pax
 
    //So, if this is the first survey OR (I know it is AND, but this is the logic I think) the last survey wasn't complete. The status of the survey is 
    //do the one before this before continueing (dummy).
    if(!startNew &amp;&amp; lastCompleted){
      status = "Pending completion of survey above.";
    };
  //If the answer array has a ZERO index, then NONE of the surveys have been completed by the respondent, So we change the flag to true for 'lastCompleted'
    if(surveyAnsArr.length == 0){
      lastCompleted=true;
    };
    //So, let's say that the respondent has answered 2 out of 4 surveys we want them to do.
    //IF the number of answers available is GREATER than the survey number we're on, THEN
    //we know that we have the answer to this question, and we can store it in the status variable 
    //which gets printed out in the table. The status is either "start" as a link to the survey, the
    //date that the survey was completed, or a message to complete the prior survey's before continueing
    if (surveyAnsArr.length-1>i){
      status = surveyAnsArr[i];
    };
    //here we create the link to the respondents other survey's using their tokens. We also pass this survey id to the linked survey
    //so the linked survey knows where to go once the respondent has completed it.
    if(lastCompleted &amp;&amp; startNew){
      //create link text here
      //server address + the survey id that we want to go to + the token for this respondent + LS junk + the subquestionid that this link is connected to + the this survey id, so that
      //the survey that we're linking to knows where to go after it is complete (this saves the LS developer from having to handcode the survey id into each of the surveys required)
      status = '<a href="'+ surveyServer + numberArr[i] + '?token='+ '{TOKEN:TOKEN}' +'&amp;amp;newtest=Y&amp;amp;lang=en&amp;qcode='+ surveySGQAs[i] +'&amp;returnSurvey=' + {SID} + '">Start</a>';
      startNew = false; //now that we've reached the next survey that must be completed, all future sureys on the lists should not have a link
    };
    //if the response array matches this particular question, then it was already completed, so we can set
    //the status to the completed date stored in the response array
    if(surveyAnsArr.length-1==i){
      lastCompleted=true;
      status=surveyAnsArr[i];
    };
      addHtml +='<td>' + status +'</td></tr>';
    };
    addHtml += "</table>";
      //add the table to the table wrapper we created at the beginning of this hot mess.
    $(table).html(addHtml);
   });
</script>

Next, you should initialize the Survey Participants token table.

At this point we are done with the Parent Survey.

The Child Survey(s)

Now, within the external surveys that you’ve listed in the Parent Survey’s surveyStatus question, you must edit the following survey settings (the external survey can actually already be a live survey for this to occur, I believe)

Within each Child Survey, open the Child Survey’s properties, and choose to edit the ‘General Settings and Text’. Then adjust the settings in the panels listed below according to the instructions:

Adjust the ‘Presentation and navigation’ settings
  1. Click on the ‘Presentation and Navigation’ panel.
  2. Find the setting called ‘Automatically load URL when survey complete’, and turn it ON
Adjust the ‘Notification & data management’ settings
  1. Click on the ‘Notification & data management’ settings
  2. Find the setting called ‘Participant may save and resume later’, and turn it ON
Adjust the ‘Tokens’ settings
  1. Click on the ‘Tokens’ panel
  2. Turn all of the setting’s off EXCEPT for the ‘Enable token-based response persistence’. Turn that one ON
Adjust the ‘Panel integration’ settings
  1. For each of the instructions below, unless you adjust the code we pasted in the Parent Survey, you MUST use what is written verbatim. Failure to do so will result in, well, failure.
  2. Click on add URL parameter
  3. Name the parameter ‘qcode’
  4. Leave the Target question as “No target question”
  5. Click on the add URL parameter again
  6. Name the parameter as ‘returnSurvey’
  7. Leave the Target question as “No target question”

Now, find the ‘End URL’ field that should be in the ‘General Text Settings’ (or something like that)
You will need to hard code the end URL. However, once you hard code it in one survey, you can just copy/paste it into all other Child Surveys. The format for the URL goes like this:

http://<”YOUR_SERVERS_ADDRESS”>/index.php/{PASSTHRU:returnSurvey}?token={TOKEN:TOKEN}&newtest=Y&lang=en&{PASSTHRU:qcode}={date("Y-n-j")}

The only two pieces of information you must provide is the server address that you use for your surveys, and OPTIONALY you can change the format of the date that will be sent back to the Parent Survey to mark the date that the survey was completed. If you want to know HOW to format it, you may just look up on this page: php.net/manual/en/function.date.php

Next, you should initialize the Survey Participants token table.

Repeat all the steps for each Child Survey you’ve included in the Parent Survey surveyStatus question.

Once you’re done – you are ready to send out survey’s with a dashboard-esque appearance.

Generating Tokens

The premise of this setup is the matching of tokens across all surveys. In order to achieve this, you must create a list of participants and either create your own tokens and upload the list to the Parent Survey AND each of the Child Surveys. OR, you can upload the list to the Parent Survey, then have Limesurvey generate the tokens for you, and then export the Participant list from the Parent Survey, and subsequently upload it to all linked Child Surveys.
The following user(s) said Thank You: tpartner, socius
The topic has been locked.
More
6 years 3 months ago - 6 years 3 months ago #160856 by cairomckenzie
Doing a Post Script to my post above to give my thoughts on how you could use the dashboard-esque workaround to solve your problem

I'm looking for a way to build an overview page that lists surveys my respondents are invited for, a respondent-side dashboard so to say. The intention is that respondents easily can see their current state (how many surveys completed yet, etc.) in a case where they are invited to participate in a series of surveys.

After you set up a parent survey with all the possible surveys a respondent would take, I imagine you could use a combination of the token table and relevancy equations for each survey listed in the surveyStatus question of the ParentSurvey. I imagine you could rig something up so that you would upload a variable into the token table attributes using a base 2 system that would represent any combination of the surveys the respondent should receive. For example

Survey 1 = 1
Survey 2 = 2
Survey 3 = 4
Survey 4 = 8
Survey 5 = 16
Survey 6 = 32
Survey 7 = 64
....etc....

Person 1 should do Survey 1, 3, and 4. So the LimeSurvey Administrator would upload a token for the participant, with an attribute value of (1 + 4 + 8 ) = 13. Then you could do some equation magic in the survey to figure out which survey's relavancy should be switched on/off.

The token tables of the surveys are identical concering Email-Adresses and tokens (i.e. respondents have the same token in all of these surveys)

In this case, you would only need to add token and email to the Parent Survey, and JUST the token to the Child Surveys. That way you manage ALL the survey's using just the Parent Survey to send reminders/invitiations.

The overview page should contain a table with the following information for each survey:
Survey1: Topic (manually entered)

I believe the current solution takes care of this.

| Survey description (ideally linked to survey)

I can't think of a way to take care of this... Maybe if there was a way to reference OTHER survey information from the Parent Survey? If this type of functionality exists, I've never dealt with it. Worse case, you just copy/paste it into surveyStatus question text.

| Median duration (calculated over all previous respondents of the survey)

This is an interesting problem to solve. My guess is that one could pass the survey duration at the end of a ChildSurvey BACK to the Parent Survey, and then have an equation that averages all responses in that answer field? In other words - the Parent Survey would have an additional question called surveyDuration which mimics surveyStatus. When the respondent completes the appropriate survey, it passes the duration value back to the Parent Survey, and stores it in the appropriate field in surveyDuration. Then perhaps you could average the durations of all responses for the particular survey? Sounds good in theory...

| Date of Invitation/Date started/Date of last Action | Started? (Y/N)/Completed? (Y/N) | Link to Survey1

I think most of these could be taken care of with Expression Manager. Except for maybe date of last action. That value exists primarily in the Child Survey Response table.... Maybe you could track it every time the 'start' link is clicked?

Let me know if you have any questions or if this is helpful to you!

Cheers.

Alex
Last edit: 6 years 3 months ago by cairomckenzie. Reason: Formatting issues.
The following user(s) said Thank You: socius
The topic has been locked.
  • socius
  • socius's Avatar Topic Author
  • Offline
  • Premium Member
  • Premium Member
More
6 years 3 months ago #160880 by socius
Hi!

@cairomckencie Alex, thank you so much for this solution and clear explanation, the well commented code and example, and your ideas to solve the rest of the problem :-) ! This is definitely more than helpful - it seems to be almost exactly what I'm looking for! In my case I wanted to allow the respondents to answer the surveys in their preferred order - but since that could lead to cherry picking interesting survey topics (each survey has a special topic) and (more) selective nonresponse, I think you solution would work well/better.

I will set this up asap. It will take me some time to completely understand the solution and the code, and to implement and test this (I'm not a programmer so this takes some days more :-) Maybe/sure questions arise on the way - I'll report my progress/success.

Seems I'll definitely have to get more knowledge on panel-integration and sharing/piping information between surveys, token tables and result tables and how-to use these to e.g. calculate the mentioned median time - I'm looking forward to dig this.

If there are other solutions to this "parent/children survey-problem" - they are all welcome :-)

@cairomckencie Thanks again!

Cheers,
G
The topic has been locked.
More
6 years 3 months ago #160895 by cairomckenzie
Great! Happy to hear. More than willing to help troubleshoot if you run into any issues.

Alex.
The topic has been locked.

Lime-years ahead

Online-surveys for every purse and purpose