anchored header to top of the screen with instructions and selection counter

Many of you may have had long list option questions also long statements making it difficult to show everything on a single screen, even if you try to break it into 2 or 3 columns

This solution allows the user to see the question instructions in a header that stays anchored at the top of the screen as the user scrolls down to see the other available statements

The selection number is also updated as you select or deselect the options, in this particular case when working with a multiple answer question type.

Again I’m using jQuery so don’t forget to add the library in your skin.

In the instruction tab, will include the instruction text and the selection counter as below:

Please select all that apply, but you must select at least 10 statements.
You have selected 0 statements

then we need some styling
So continue adding this, you can also define all these styles right in the Confirmit styles menu.


and finally the javascript, that has two parts, one is to make the header anchored at the top and the other one is for updating the selection counter as you select or deselect the answers.


Here’s a link to see everything together
http://jsfiddle.net/confirmitexpert/GBv58/embedded/result/

It works in all browsers, but the jsfiddle link above doesn’t work in IE, so please fell free to use Firefox, Chrome etc.

Give it a try and let me know what you think!

Confirmit dynamic questions with a twist

We know Confirmit has the option to trigger a second question (or more) based on a previous question answer, you may find this called dynamic questions.
You need to use a page object and add the questions inside then choose “triggers” on the ones you need to have them triggered.
You can define complex logic and all the other functionality such as text piping, question masking etc. can be controlled by the trigger function, so you can take advantage of all these.

That’s a pretty cool feature that allows you to chain some logic and have it working on the same page.

The downside of this is that the positioning on the screen of the second question is not always easy.
Also the logic is only evaluated when the page is submitted (when the respondent clicks the Next button), and sometime is hard to follow when the logic is complex.

I will present a different alternative for the triggers (or dynamic questions):

The set up will be the same, 2 questions on the same page, the second will be triggered by answering an option from the first question. In this example I’m using 2 multiple questions.
The second question will show up right under the option that triggers it, so its answers will nicely align under it.

In the answer label we need to use for triggering the second question will insert an empty div tag with a class, let`s call it “willTrigger”, this will help us identify which one is the one we will need to check if is clicked (checked) or not.

In my example I have this answer label to trigger the second question

Product ingredients

Here`s the script that makes all this possible, again I`m using jQuery, so don`t forget to include a reference to jQuery library in your skin:

$(function(){
    //the fieldset_q8m below is the second question fieldset name, so if your question is q11 that will change to fieldset_q11
    var trigered = $('#fieldset_q8m').parents('.questionarea');
    trigered.addClass("hidden1").removeClass('questionarea').hide();
    //add an empty tdr/td
    $('.willTrigger').closest('tr').after('<tr><td colspan=2>');
    //and populate with the hidden div
    $('.willTrigger').parents('tr').next('tr').find('td').html(trigered);
    //test input change, will also hide the error message if the answer was de-selected
    $('.willTrigger').closest('tr').find('input').change(function(){
        $(this).is(':checked')?trigered.show():trigered.hide(), $('.error_msg').hide();
    });

    // here will bind a bit of logic checking if the second question was answered
    $('form').bind('submit', function(){
        if($('.willTrigger').closest('tr').find('input').prop('checked') && !trigered.find('input:checked').length>0){
            $('.error_msg').show();
            return false;
        }
        else {
            return true;
        }
    });
});

I also created a custom style in the confirmit css styles, named “hidden1”, I’m adding to the triggered question

.hidden1{
    margin-left:10px;
}

so that its answers will be nicely aligned under, creating the impression of being part of the first question answer, like an inline answer list

Will also create some logic to check if the second question is answered before the form is submitted, so will need to create an error message like

Please select at least one ingredient

and also define this in the confirmit style list

.error_msg{
    display:none;
}

or just add the “display:none” inline


The “errorquestion” class is the default error style already defined in confrmit

The erro message div add it in the first question “instruction” tab, the script can also be placed there.

Here’s a fiddle example to see how it works, click on the “Product ingredients” and try to click next without giving any other answers there, see how the script detects the missing answers and reacts.

http://jsfiddle.net/confirmitexpert/rvPCK/embedded/result/

Do you often use the Confirmit default capabilities, or like to create everything from scratch, and have it fully customized?

Let respondent change the questionnaire language on the fly

After I published the last post I was thinking if the language example I picked was relevant or not, in fact, there’s a simpler way for an user to change the current language, in real time, without so much complex code and option changes I described in the previous post.

Here’s an easier way to let the user change the language.

Everything happens in the theme (main theme)
There`s no need to change any of the options from the “survey Settings”, link security like “unencrypted QID” or allow changing the previous answers etc, this will work with the default settings.

First we need a button or similar element,

<div class="navigationarea">
<input class="navbutton confirmit-nav" onclick="changeLanguage()" alt="" value="Switch to ^CurrentLang()=='9'?'French':'English'^" size="20" type="button"/>
</div>

As you can notice, the onclick event calls this changeLanguage() function, and its content is below:

function changeLanguage(){
    var lang= "^CurrentLang()^";
    location.href="^GetRespondentUrl()^"+String.fromCharCode(38)+(lang=="9"?"l=12":"l=9");
}

So far so good, everything works, but still there’s this screen

You have already completed parts of the questionnaire.
Press OK to continue.

Every time you click the button you get this screen (with the default settings)

To make the process smoother we will detect that page, “Internal_Continue_survey_on_entry_text”, hide its content, (please make sure you use the same wrapper class for the div that surrounds your content if not please replace it with your own), and submit the form

$(function(){
   if( $("#Internal_Continue_survey_on_entry_text").length>0 ) {
       $(".wrapper").hide();
       document.ctlform.submit();
   }
});

So let’s add everything together, please place this let’s say at the end of your main theme, right after the navigation component. In the layout tab use the code editor, not the WYSIWYG.
Don’t forget to include the jQuery library in the external js
“External Javascript Url” like https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js

All added together below


<div class="navigationarea">
<input class="navbutton confirmit-nav" onclick="changeLanguage()" alt="" value="Switch to ^CurrentLang()=='9'?'French':'English'^" size="20" type="button"/>
</div>

Easy real-time survey interaction

Today’s subject is about a nice technique that allows you, I mean the respondent, to interact with almost anything from inside the survey in a very transparent way, whenever they want and are allowed, of course.

You may find this helpful if you do iPad/mobile surveys on-site as well.

This can go from changing the theme UI (don’t think about setting up any cookies though!), the language, till changing or going into a specific module then come back and complete the rest.

The example I picked is to let the respondent change the questionnaire language in real time (you need to have the language and the corresponding texts added already in Confirmit) and this can be extended to anything else you may think about.

The set up is easy, and as you can see in the image below we need some variables:

setup folder

“language” is the background “language”, and let’s say we’ve got English and French, precodes 9 and 12.
“l” we’re using to control the current language, this reflects in the language the questionnaire is displayed in.
the “set language” script has the following content:

if(! f('l').toBoolean()) f('l').set(f('language').get());

the “qleft” is an open end that stores the survey current question ID (is updated every time the page loads)
and below is the “scripts” node content, I’ve added it here to quickly see how “qleft” gets updated with the questionID, the function setQLeft being called from the theme

function setQLeft(){
  var currentForm=CurrentForm();
  
  if (currentForm!="lch") f('qleft').set(currentForm);
}

function langDisplay(){
  return f('l').get()=='9'?"French":"English";
}

Notice the test if currentForm!=”lch” so we don’t set it if this question, otherwise we end up in a loop

The langDisplay helps in the survey theme, returning the language string you want to switch into

next there’s a condition node set to false, meaning this will be never executed in the normal flow

“lch” is an info question type with the content as follows

wait...

The next script node is setting the new language, and then redirects them where they left

f('l').get()=='9'?f('l').set('12'):f('l').set('9');

Redirect(GetRespondentUrl()+"&__qid="+f('qleft').get(),true );

and lastly, the script to redirect back where they left

if ( f('q1').toBoolean() && f('qleft').toBoolean() ) {
  Redirect(  GetRespondentUrl() + "&__qid=" + f('qleft').get(), true);
}

Next step is to add and call some of these function from inside the theme since we need to make them visible and allow the respondents interact with them somehow.

main theme layout custom change language button

As you can notice -red square- setQLeft is called every time the page loads, and once it’s executed it writes the questionID (currentForm) so the last question id if there are multiple per page

the second – green square- is a javascript function that will change the location url and sends him to the specific questionid lch (language change)
Tips String.fromCharCode(38), I used this instead of simple adding the “&” character, Confirmit always replaces the “&” with “& amp;”

and third – blue square- a button that runs at on click the function above, and also notice its value is defined as a function call from langDisplay that returns the language you want to change into

^setQLeft()^


Last you need to make some changes in the Survey Settings tab
“General Options”
Uncheck “Disable unencrypted QID request parameter (recommended to prevent respondents from tampering with the survey urls to skip to specific questions)”
“Web Options”
Check “Allow respondents to change their original answers”

The reason I used the question id as the solution to jump between questions was because you can control exactly where and how.

I learned you can do something similar now using the blocks and calling them when you jump, but didn’t have the opportunity to test everything, maybe you guys are already using this approach?

isEmailTaken, isUsernameTaken and two non-standard ways to use them

The two functions are more related to the respondent recruitment surveys and are used to check if any previous respondents have registered with the same email address or user name. They are not really known, but they’re really powerful.

The power comes from the the fact they give you access to the global data, from inside a respondent link. I always wished for some Confirmit internal functions to call and get access to other individuals responses, from inside a script. I know there are all kind of alternatives from a simple API app, or even using a scripting extension, but nothing I know that’s already available in Confirmit. (not sure if there’s anything planned for Confirmit 16).

Anyways, we have these two associated with their question IDs “email” and “username” and as I said, here are two simple scenarios that demonstrate how we can use them in a regular survey.

A first scenario would be an open link survey, let’s say we have it distributed to a number of websites and later in the survey or at the end, we collect their email address for another follow up (right after this first survey) and you don’t have time to collect all the emails and sort/eliminate duplicates and so on.

It’s nothing easier than creating an open end question with “email” as questionID, make it look nice, one row etc
then add a condition node, and call the function

!isEmailTaken( f("email").get())

depending on the logic, you can use a redirect to the second survey or just terminate.

The second example is a little bit more complex and is outlined below:

We want to give 100 free Amazon vouchers or another electronic incentive to the first 100 respondents who complete the study. We can even add a note it in the invitation letter, to boost the response rate… (First 100 respondents get a 5.00$ voucher etc).

The issue is that we need to assign an unique voucher number to a respondent who completes the study. Forget the idea of pre-assigning them when they start, we may or not have enough vouchers to use, and who will stay to sort everything after all?

function vouchers(){
var labelsArr=f("vouchers").domainLabels();
/*the vouchers is a multi randomized question with the vouchers as answers
//if more values are required, you can always create a set, and use a standard randomize script, you can find in any scripting manuals
//vouchers and username are hidden question
*/
f("username").set(labelsArr[0]);
var found = false;
var counter=1;
while (found==false && counter<labelsArr.length){
	if(isUsernameTaken(f("username").get())){
		f("username").set(labelsArr[counter]);
		counter++;
	}
	else found =true;
}
return found;
}

you may call the function from a condition node or script node then redirect/or not the respondent to Amazon and claim their free voucher

As a last note, these are working as global variables, it doesn’t matter what the respondent status is, the functions will check even if the respondent has the incomplete status.

Randomly respondent allocation controlled by quota

Just finished a study today for one of my clients and he asked if it’s possible to expose his respondents to three different brands, with a max of 500 per each.

The easiest method we can think off is by pre-setting a background single variable; we have 500 per each times 3 so we need 1500. (that’s after screenings – if any).
To have a round number, of course depending of the projected incidence as well, let’s say we may size the sample to 2400 people.
Now randomly have a background single variable set, let’s call it brandAllocation, with precodes from 1 to 3.
we’ll get 800 people with brandAllocation set to 1, 800 people with brandAllocation set to 2 and so on.

The issue is you can’t control them, so you may end up in loosing sample, I mean valid respondents get screened out because of quota, and may end up in not having the required number of completes on one or even all three brands.

This situation can be avoided if we have some controlled allocation, based on quota.

First, we need to have the same brandAllocation question, this time is hidden and the answers randomized. Why randomized? It’s easier to let Confirmit randomize it for us.
Nest step is to create a quota and drag this single question inside and specify the limits for each brand you need the respondents to be exposed.

Here is the function I used. Just place it in a script node.

function checkQuotaSingle(questionId,quotaName){
	var qIdDomainValArr = f(questionId).domainValues();
	f(questionId).set(qIdDomainValArr['0']); 
	var tempVal = f(questionId).get(); 
	var foundBool = false;

	for (var i = 0; i < qIdDomainValArr.length; i++) {
		if(qf(quotaName))f(questionId).set(qIdDomainValArr[i]);
		else { foundBool = true; break;}
	}
return foundBool;
}

The usage it's simple, after the screening questions, have a condition node with the function call

!checkQuotaSingle('q1','quota1') 

then
Stop (quota full)

The advantages are:
you can control the limits for each of the brands, so if you change your mind during the field you can easily do it.
the sample (as calculated earlier) would be enough to fill the quotas up, and actually even less sample would be needed.

Redirect to a different project or web application, and capture data back

Here is a technique I used in various projects I was working on, where I had to link to a different project, modules or third party applications, pass some data and collect other data back.

Start by creating a script node with the content below:

var applicationUrl="the_application_url";
var theRespondentUrl=HttpUtility.UrlEncode(GetRespondentUrl()+"&__qid=backFromApp");
//or since Confirmit15 GetRespondentUrl("backFromApp");
var x,y="";//here some variables and values, you can take those from other questions as you wish
var additionalVariables="&x="+x+"&y="+y;
Redirect(applicationUrl+"?linkBack="+theRespondentUrl+additionalVariables,true);

Next, add an info question, with the ID backFromApp, and here is the place where we expect to have the respondent returned,

<input type="hidden" name="dataCaptured" id="dataCaptured">
<script type="text/javascript">
function getUrlVariables(){ 
  var variablesUrl = [], variableNameValue; 
   var variablePair = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); 
    for(var i = 0; i < variablePair.length; i++)    { 
       variableNameValue = variablePair[i].split('='); 
       variablesUrl.push(variableNameValue[0]);  
       variablesUrl[variableNameValue[0]] = variableNameValue[1]; 
   }
  return variablesUrl;
}

document.ctlform.dataCaptured.value=getUrlVariables()[ 'oneInParticular'];//store data in hidden form element, dataCaptured
document.ctlform.submit();//go to the next question
</script>

Please make sure you use the right variable name, since it’s case sensitive.

A script node follows the info question above, and stores the data back in Confirmit, let’s say you have an open end with the id “dataCaptured”

f('dataCaptured').set(Request('dataCaptured'));

On the other end (in the external app, or even Confirmit project) you only need to capture the link, store it, append the data and redirect the respondent back.

Avoid getting the same respondent entering multiple times an open survey – cookies

When it’s possible to have a survey deployed on different sites, you may end up having same people entering multiple times.

Or let’s say you may have a category survey and you want to make sure people can’t participate within one month from the time they have completed a same category survey.

You are able to control this using the browsers cookies.
Here are two functions one to write and the other one to check if there are any cookies

function WriteCookie(category){
	var mycookie : Object = new HttpCookie(category);
	var now : DateTime =  DateTime.Now; 

	mycookie.Path = "/";
	mycookie.Value = CurrentPID()+"|"+category;
	mycookie.Expires = now.AddMonths(1); 
	Response.Cookies.Add(mycookie);
}


function ReadCookie(category){
	var mycookie : Object = Request.Cookies(category);

	if(mycookie != null && mycookie.Name==category) return true;
	else return false;
}

Now, when is the best time to write the cookie out? Best would be at the time the panelist gets the status ‘complete”, just call the function from a script node

WriteCookie('category1');

To check if the cookie is already set, right when the survey starts, you can add a condition node like

if ReadCookie('category1')
then
 

Another usage of cookies is not only checking the cookie name but checking the values we’ve stored,
So now we store here the ProjectID and the category string:

mycookie.Value = CurrentPID()+"|"+category;

you also can read it

myCookieValue=myCookie.Value;

and parse it or split it by “|”
then you can check the values form there.

myCookieValues=myCookie.Value.split('|');

Calling confirmit functions from inside the theme. Part2: dynamic content

One other possible usage of calling functions from a theme is to actually display a piece of html code dynamically created inside the survey.

Here is one example of a function that based on a question answer returns an image string:

function content(){
var content="";

if (f("q1").get()=="1") content="<img src=\"images/top1.png\" />";
else content="<img src=\"images/top2.png\" />";

return content;
}

Just place the function call in the theme,

^content()^

What will happen is that if the answer with precode 1 is selected it will return the first image if not it’s the second image returned

Based on this simple example you can come with more complex content, depending on your needs, you can also have the logic based on background variables, like language, or gender etc.

And don’t forget to deselect the option “Html encode output of piping expressions” before compiling

Automatically close a project when quota is full using Confirmit APIs (C# .NET) & JSONP – Part1

Surely by now, if you were in Confirmit world long enough, you must have heard questions about closing studies automatically when a quota is reached.
If you’ve ever asked to do this, I’m pretty sure the answer was Confirmit has nothing to accommodate this.

If you have access to Confirmit APIs means you can say now, I have something!

This solution comprises two parts:

  • An application (done in C# .NET) that connects to the APIs and closes the project
  • The actual call directly from inside the survey (that needs to be closed). For this I’m using a JSONP technique since you never know where the app ends being hosted, plus this offers you a little bit more control over it.

Before starting, make sure you have access to Confirmit APIs (your user has to have some special permission).

Since this is done in .NET you start by creating a new Web site and add (Add web reference) two of the Confirmit WS: LogOn and Authoring, LogOn is needed for authorization reasons.

The links to connect to the APIs are in the following format:
your_confirmit_domain/confirmit/webservices/version/service
where version is your Confirmit version like 15.0 and service is one of the available services Confirmit APIs has here is an example: LogOn.asmx

Ok so now after you’ve added them you may see something similar
Confirmit WS reference

AuthConfirm(): authenticate and get a key back.

    private bool AuthConfirm(){

        Confirmit.LogOn logOn = new Confirmit.LogOn();
        try{
            key = logOn.LogOnUser(ConfigurationManager.AppSettings["username"]
                , ConfigurationManager.AppSettings["password"]);
        }
        catch{}
        if (key.Length == 0){       // Login failed 
            Response.Write("callback({\"status\":\"error\"});"); 
            return false;
        }
        else return true;
    }

CloseProject() sets the SurveyStatus to Closed

    protected void CloseProject(string pid)
    {
        myAuth = new Confirmit.Authoring();
        mySchema = myAuth.GetProjectInfo(key, pid);

        try {
            myAuth.SetSurveyStatus(key, pid, Confirmit.SurveyStatusType.Closed);
            myAuth.Update(key, pid, mySchema);
            Response.Write("callback({\"status\":\"closed\"});");
        }
        catch
        {
            Response.Write("callback({\"status\":\"failed\"});");
        }
        
    }

Let’s put them together now

   protected void Page_Load(object sender, EventArgs e)
    {   
        string projectId = Request.QueryString["projectId"];
        if (projectId != null && projectId != ""){
            if (AuthConfirm()) CloseProject(projectId);
        }
        else
            Response.Write("callback({\"status\":\"projectId\"});");

    }