Welcome to the LimeSurvey Community Forum

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

Modern Conjoint Experiment with Per-Respondent Profile Randomization

More
3 weeks 1 hour ago - 3 weeks 51 minutes ago #273599 by baristurkdogan
Please help us help you and fill where relevant:
LimeSurvey version: 6.16.4
Own server or LimeSurvey Cloud: LimeSurvey Cloud
Survey theme/template: fruity_twentythree

==================
Hello Dear Community, 

Goal & Context
I'm trying to build a conjoint analysis / discrete choice survey for a social science experiment, where I'd like to measure preferences for student scholarship recipients.The survey needs to:
  • Present 10 sequential choice tasks
  • Each task shows 2 student profiles side-by-side in a table
  • Respondents select which profile they prefer
  • Each respondent sees different random profiles (full per-respondent randomization)
    • BUT Name Restriction: EITHER no profile with the same name appears more than once per respondent OR the profile with the same name appears with the same attribute levels if they appear more than once per respondent (whichever is more feasible)
  • Radio buttons embedded in the table cells for selection
 This is a modern conjoint design based on the seminal "Causal Inference in Conjoint Analysis: Understanding Multidimensional Choices via Stated Preference Experiments" article by Hainmueller et al. (2014) where I need independent randomization of attribute levels across respondents, not just fixed profile sets repeated for all respondents.
 ---
Profile Attributes & Levels: 5 attributes in total
Attribute: Levels // (Notes) 
1. Name: Leon Schmidt, Lukas Müller, Jan Fischer, Paul Wagner, Jannik Weber, Tom Becker, Jonas Meyer, Emil Lehmann, Niklas Scholz, Luca Hartmann, Arda Yılmaz, Emre Kaya, Can Demir, Baran Şimşek, Deniz Güneş, Mehmet Öztürk, Kaan Kılıç, Efe Kaplan, Ömer Çalışkan, Ali Yıldız // (10 German-sounding and 10 Turkish-sounding names, 20 names in total)  
2. Field of Study: Mechanical Engineering, Law, Psychology, Business Administration // (4 fields) 
3. Grade (GPA): 1.3 (Very Good), 2.0 (Good), 2.7 (Satisfactory) // (3 grades according to the German grading scale)
4. Extracurricular Activity: Student Parliament, Sports Club, Music Tutor, Food Bank Volunteer // (4 activities) 
5. Semester: 3rd semester (Bachelor), 5th semester (Bachelor), 3rd semester (Master) // (3 semesters) 

Design: Profiles are factorially designed combinations of all attributes (~2,880 unique profiles generated from these attribute levels). BUT the NAME RESTRICTION should be applied.

 --- Desired Table Display -> Should look something like the CAR example (see attached below) in Tutorial_Gimmicks Chapter 11  (second image in the chapter) but I couldn't somehow replicate it. ---

Key Challenges I've Encountered 
1. Per-Respondent Randomization
- Problem: I initially created 10 fixed HTML files with hardcoded profile pairs (run once, same for all respondents)
- Why It Failed for Conjoint: This violates the core principle of conjoint analysis—attribute levels need to vary independently across respondents so I can isolate individual attribute effects
- What I Need: Each respondent should see 10 different random profile pairs (profiles A and B drawn randomly from the pool of 2,880, applying the name restriction) 

2. Radio Button Placement in Table Cells
- Problem: Attempted to use "Tutorial_Gimmicks Chapter 11" method (JavaScript DOM manipulation) to move radio buttons into table cells
- Why It Failed: LimeSurvey 6.x appears to have security restrictions or structural issues that prevent reliable DOM access to radio button elements
- What I Need: Radio buttons should be clickable and positioned directly in the bottom row of the profile table (appear as if they're part of the table layout) 

3. JavaScript Execution in LimeSurvey 6.x
- Problem: JavaScript in question text (Source Mode) sometimes fails silently—no console errors, but functionality doesn't execute
- What I Need: Either a working JavaScript solution OR an alternative approach (e.g., custom question type, plugin, or alternative rendering method) 

--- 

Attempts Made (For Context)
I've tried:
1. ✗ JavaScript in question HTML with `document.addEventListener()` and `setTimeout()` to move LimeSurvey's auto-generated radio buttons
2. ✗ Static hardcoded profile pairs (worked visually, but not true conjoint randomization)
3. ✗ Embedding `<input type="radio">` elements directly in HTML and using JavaScript to trigger LimeSurvey's answer recording 

---


***QUESTIONS*** 

1. Randomization: What's the best approach to achieve per-respondent random profile selection in LimeSurvey 6.x?   
- Should profiles be stored in a hidden field or database?   
- Can LimeSurvey expressions or tokens generate random indices?   
- Is there a plugin or extension for this? 

2. Radio Button Placement: How can I reliably embed/position radio buttons inside table cells while maintaining LimeSurvey's answer recording?   
- Does the Chapter 11 method work in LimeSurvey 6.x, or has it changed?   
- Are there CSS-only solutions to reposition the radio buttons?   
- Should I use a custom question type? 

3. Alternative Approaches: If JavaScript/DOM manipulation isn't reliable, are there other ways to build a conjoint interface in LimeSurvey?   
- Custom question type development?   
- Integration with external JavaScript libraries?   
- Database-driven dynamic content? 

--- 

Any guidance on how to properly implement a modern conjoint analysis with full randomization and proper table layout in LimeSurvey 6.x would be greatly appreciated. Happy to provide more details, sample files, or clarifications.Thanks in advance!
Last edit: 3 weeks 51 minutes ago by baristurkdogan. Reason: display issues

Please Log in to join the conversation.

More
3 weeks 40 minutes ago - 3 weeks ago #273604 by Joffm
Hi,
Some remarks.

Obviously you didn't use the "green apple - banana" example that is show here many times.
I admit your shown image uses this approach.

Now some answers.

Each respondent should see 10 different random profile pairs (profiles A and B drawn randomly from the pool of 2,880, applying the name restriction)

So thew profiles are there already and are not generated during the survey.
That's not to difficult with some ExpressionScript.

Should profiles be stored in a hidden field or database?

Depends, hidden field is easier, but you should show more details about it.
Database? Hm, I see, you use a Cloud version. Don't know if an ajax call is possible. But you could parse a csv file (Buzzword "Papaparse").

Conclusion:
You don't need more than
  • the layout with embedded radio buttons
  • the selection of 10x2 profiles out of 2880
Now it's your turn.

Send an example of some of the profiles (to get a feeling about the number of characters per profile) 
and the lss export of your survey (only this part)

Some examples (you are absolutely free how to create the table)
1. A question design without any javascript only built in features
 
2. Some kind of the mentioned "green apple - banana" example (to show that the buttons can be inserted anywhere)
 
The main part is to create the HTML table.
Then some lines of javascript to move the buttons and 
Code:
<script type="text/javascript" charset="utf-8">
  $(document).on('ready pjax:scriptcomplete',function(){
 
    // Identify this question
    var thisQuestion = $('#question{QID}');
 
    // Move the radios
    $('.question-text table:eq(0) tr:eq(3) td:eq(1)', thisQuestion).prepend($('.subquestion-list .answers-list:eq(0) .answer-item:eq(0) *', thisQuestion));
    $('.question-text table:eq(0) tr:eq(3) td:eq(2)', thisQuestion).prepend($('.subquestion-list .answers-list:eq(0) .answer-item:eq(1) *', thisQuestion));
// and so on
 
    // Some classes for presentation
    $('.question-text table:eq(0) input:radio', thisQuestion).closest('td').addClass('answer-item radio-item text-center radio');
    $('.question-text table:eq(0) .radio-item label', thisQuestion).show();
    // Click event on the table cells
    $('.question-text table:eq(0) .radio-item', thisQuestion).on('click', function(e) {
      $('input:radio', this).trigger('click');
    });
    $('.question-text table:eq(0) input:radio', thisQuestion).on('click', function(e) {
      e.stopPropagation();
    });
 
// Followed by some cleaning


Joffm

P.S. Da Du ja offensichtlich mein deutsches Tutorial gelesen hast, hättest Du besser auch im deutschen Teil Fragen dazu gestellt.
Und hättest auch die dort befindliche Beispieldatei herunterladen und installieren können. Das hätte viele Fragen beantwortet.
Warum muss ich immer ohne Not Englisch schreiben?

 

Volunteers are not paid.
Not because they are worthless, but because they are priceless
Last edit: 3 weeks ago by Joffm.

Please Log in to join the conversation.

More
2 weeks 6 days ago #273608 by baristurkdogan
Hello again Jofm, 

Thanks for the guidance! I'm preparing to implement your solution.

Please see attached:
1. Sample profiles (first 5 rows + header) - shows format and ~150 characters per profile
2. LSG export of my ConjointTasks group (currently just a hidden field placeholder)

How would you suggest I proceed?

Thanks again!

P.S. I'm just an international student studying in Germany, I don't speak German. You cited your Tutorials so many times here that I decided to auto-translate them   Falls es Ihnen auf Deutsch leichter fällt, kann ich den Forumtext auch automatisch übersetzen, so wie ich es hier getan habe. Kein Problem.

Please Log in to join the conversation.

More
2 weeks 6 days ago #273610 by Joffm
Hi,
in the meantime I thought about the selection.
You only need (or better, what I used):
1. A pool - a question of type long text.
In the default answers all 144 possible combinations of your attributes with a autoincrement number, like
001:1111
002:1112
003:1113
004:1121
...
142:4341
143:4342
144:4343

2. A question of type multiple short text. Here we do the randomisation by javascript
a. Names: create an array of numbers '01','02',...'19','20' representing the 29 names. You could use characters 'A', 'B', 'C',... as well.
Shuffle this array
b. Profiles: create an array of numbers '001','002',...'143','144' representing the profiles.
Shuffle this array and use the first 20 elements.
You will get something like this


3. I like to use an array(text) (6 rows, 2 columns) as container for intermediate results. This way you save questions.

4. Equations to grab the values from the "pool", (functions "strpos", "substr")
to "translate" the numbers to the text

Finally you get this array
 
which you use to pipe the text into the tables of the 10 questions

Now it is only necessary to copy the equations and adapt the "substr" indices.

I will send an example of this my idea tomorrow.

Joffm

P.S.
Neither send lsq nor lsg exports; only lss.


 

Volunteers are not paid.
Not because they are worthless, but because they are priceless

Please Log in to join the conversation.

More
2 weeks 5 days ago - 2 weeks 5 days ago #273621 by Joffm
Hi,
since yesterday I found a new approach that avoids a lot of nested IFs.

In the following ALL subquestion codes are numerical (1,2,...)

A. Group GCalc (here we initialise the whole stuff)
1. As already said, in a (hidden) question of type "long text" (Pool) insert all 144 possible combinations in this form.
Order: field (4), grade (3), activity (4), semester (3)
001:1111
002:1112
...
088:3221
089:3222
...
143:4342
144:4343

2. In a question of type "multiple short text" (QSelect) with two subquestions enter this script to 
  • randomize the 20 names
  • randomly select 20 profiles
Code:
<script type="text/javascript" charset="utf-8">
function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;
  // While there remain elements to shuffle...
  while (0 !== currentIndex) {
    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }
  return array;
}
 
$(document).on('ready pjax:scriptcomplete',function(){
  // Fill the array with 20 characters
  var arr = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T"];
  arr = shuffle(arr).join('');
  $('#question{QID} input[type="text"]:eq(0)').val(arr);
 
  // Fill the array, numbers from 1 to 144
  var arr1 = ;
  for (var i = 1; i < 145; i++) {
    var x = i.toString().padStart(4,"0").slice(-3);
    arr1.push(x);
  }
  arr1 = shuffle(arr1).slice(0, 20).join('');
  $('#question{QID} input[type="text"]:eq(1)').val(arr1);
  //$('#question{QID}').hide();
});
</script>

Hide this question with css-class "d-none"

3.
  • Create a (hidden) question of type "multiple short text" (PComb) with two subquestions to temporarly store the selected profiles
  • Create (hidden) questions of type "list(radio)" to store and retrieve the texts.
    PName1 and PName2 with answer options "A: Leon Schmidt", "B: Lukas Müller",...; "T: Ali Yıldız" (You see the coding refers to the characters in the script)
    PField1 and PField2 with the four answer options of Field of study, coded 1,2,3,4
    PGrade1 and PGrade2 with the three answer options of Grade, coded 1,2,3
    PActive1 and PActive2 with the four answer options of activities, coded 1,2,3,4
    PSem1 and PSem2 with the three answer options of Semester, coded 1,2,3
4. Because QSelect is hidden by css there would be displayed the skeleton of a question.
Therefore you may show a question of type "text display" with a message like "The profiles are initialised"
With this script you hide the buttons and proceed after some seconds
Code:
<script type="text/javascript" charset="utf-8">
      $(document).ready(function(){
            // Verstecke den „Weiter“-Button
            $('#ls-button-submit').hide();
             $('#ls-button-previous').hide();
 
            setTimeout(function () {
            $('#ls-button-submit').trigger('click');
          }, 3000);  //  3 Seconds, Value in milliseconds
});
</script>


That's all to initialise nearly everything.
Now you create the ten groups with two questions in each group
5. Create a (hidden) question of type "equation" where you set the hidden list(radio) questions with ExpressionScript.
(The advantage is: We only use numbers, but show the text with the property ".shown")

a. eqSet1
We capture the first and the second character of QSelect_1 (names)
and search the combination that matches the first and second number in QSelect_2 (remember: these numbers are three digits long)
Code:
{PName1=substr(QSelect_1,0,1)}
{PComb_1=substr(Pool,strpos(Pool,join(substr(QSelect_2,0,3),':'))+4,4)}
 
{PName2=substr(QSelect_1,1,1)}
{PComb_2=substr(Pool,strpos(Pool,join(substr(QSelect_2,3,3),':'))+4,4)}
 
{PField1=substr(PComb_1,0,1)}
{PField2=substr(PComb_2,0,1)}
{PGrade1=substr(PComb_1,1,1)}
{PGrade2=substr(PComb_2,1,1)}
{PActive1=substr(PComb_1,2,1)}
{PActive2=substr(PComb_2,2,1)}
{PSem1=substr(PComb_1,3,1)}
{PSem2=substr(PComb_2,3,1)}

b. eqSet2
and in the second we only have to change the indices in "PName1, PName2" and "PComb_1, PComb_2"
Code:
{PName1=substr(QSelect_1,2,1)}
{PComb_1=substr(Pool,strpos(Pool,join(substr(QSelect_2,6,3),':'))+4,4)}
{PName2=substr(QSelect_1,3,1)}
{PComb_2=substr(Pool,strpos(Pool,join(substr(QSelect_2,9,3),':'))+4,4)}
 
{PField1=substr(PComb_1,0,1)}
{PField2=substr(PComb_2,0,1)}
{PGrade1=substr(PComb_1,1,1)}
{PGrade2=substr(PComb_2,1,1)}
{PActive1=substr(PComb_1,2,1)}
{PActive2=substr(PComb_2,2,1)}
{PSem1=substr(PComb_1,3,1)}
{PSem2=substr(PComb_2,3,1)}

6. The second question in each group is your question.
This  is a question of type "array" with one subquestion and two answer options.
Design your desired HTML table with a last row to show the radio buttons.
Like (very rough, without any styling)
Code:
<table border="1" cellpadding="0" cellspacing="0" style="border-collapse:collapse;" width="100%">
    <tbody>
        <tr>
            <td>Which profile do you prefer?</td>
            <td><strong>Profile 1</strong></td>
            <td><strong>Profile 2</strong></td>
        </tr>
        <tr>
            <td>Name</td>
            <td><strong>{PName1.shown}</strong></td>
            <td><strong>{PName2.shown}</strong></td>
        </tr>
...
        <tr>
            <td>Semester</td>
            <td><strong>{PSem1.shown}</strong></td>
            <td><strong>{PSem2.shown}</strong></td>
        </tr>
        <tr>
            <td><b>Your choice</b></td>
            <td> </td>
            <td> </td>
        </tr>
    </tbody>
</table>


You show the texts of the profiles in the cells with {PName1.shown}, {PField2.shown},...
To move the radios into the table use this script
Code:
<script type="text/javascript" charset="utf-8">
  $(document).on('ready pjax:scriptcomplete',function(){
 
    // Identify this question
    var thisQuestion = $('#question{QID}');
 
    // Move the radios, you see they are inserted in the second and third column (td:eq(x)) of the last row (tr:last)
    // And the first and second answer option are affected (answer-item:eq(x))
    // Remember it is zero based. 
    $('.question-text table:eq(0) tr:last td:eq(1)', thisQuestion).append($('.subquestion-list .answers-list:eq(0) .answer-item:eq(0) *', thisQuestion));
    $('.question-text table:eq(0) tr:last td:eq(2)', thisQuestion).append($('.subquestion-list .answers-list:eq(0) .answer-item:eq(1) *', thisQuestion));
 
    // Some classes for presentation
    $('.question-text table:eq(0) input:radio', thisQuestion).closest('td').addClass('answer-item radio-item text-center radio');
    $('.question-text table:eq(0) .radio-item label', thisQuestion).show();
 
    // Click event on the table cells
    $('.question-text table:eq(0) .radio-item', thisQuestion).on('click', function(e) {
      $('input:radio', this).trigger('click');
    });
    $('.question-text table:eq(0) input:radio', thisQuestion).on('click', function(e) {
      e.stopPropagation();
    });
 
    // Clean-up styles
    $('.answer-container', thisQuestion).hide();
    $('.question-text table:eq(0) .label-text', thisQuestion).remove();
    $('.question-text table:eq(0) .radio-text', thisQuestion).css({
      'cursor': 'pointer'
    });
    });
</script>

The big advantage is:
In the equations you only have to changes the indices
You can copy this question into all other groups without any changes.

This way you will get the following in the response table

You see the first profile (red): the character of the name and the codes of the four attributes
You see the second profile (blue): the character of the name and the codes of the four attributes
And in the next question the answer code.

Here the survey structure
 

Now it's your turn.
Try to create this.
If there are questions send the lss export (and not only two empty questions)
You see: In your first post you mentioned many attempts that failed. Why didn't you show them? Maybe there were real good ideas where only a minor tweak made them run.

And we always ask for lss exports (neither lsq nor lsg).
These other exports are language sensitive. You can only import them into a survey with the same base language.
So ease our work, that we don't have to guess a language, create a survey, create a group to be able to import a lsq export.
Furthermore these exports don't contain the survey wide settings that may be of importance, too.

Joffm

BTW:
If you prefer to use your csv file you may have a look at [url] www.papaparse.com/ [/url]
 

Volunteers are not paid.
Not because they are worthless, but because they are priceless
Last edit: 2 weeks 5 days ago by Joffm.

Please Log in to join the conversation.

More
2 weeks 4 days ago #273623 by Joffm
A small addition.
This usually used table is not very suitable for respondents on small devices.
To cover these people you may consider to use the display option with the library "tinyslider"
[url] github.com/ganlanyuan/tiny-slider [/url]
[url] ganlanyuan.github.io/tiny-slider/demo/ [/url]

On wide screens you see the "normal" view
 
while on smaller screens you see less, but with a small (so called) edgepadding to indicate that there is more to see. The respondent just swipes through the options
 


You find a full example in the sample file of the tutorial (Group G11d)

Joffm

Volunteers are not paid.
Not because they are worthless, but because they are priceless

Please Log in to join the conversation.

More
2 weeks 4 days ago - 2 weeks 4 days ago #273625 by baristurkdogan
Hi, 

Thanks for the detailed guide.

I followed your roadmap but the profile attributes aren't populating in my table—only the structure shows (see the attached table display). What might be the issue causing this? I also attached my Lss file. 

Thanks again.
Last edit: 2 weeks 4 days ago by baristurkdogan.

Please Log in to join the conversation.

More
2 weeks 3 days ago - 2 weeks 3 days ago #273626 by Joffm
Hi,
your mistake was not to enter the values as "default answer" in "Pool".
I admit I did not mention this explicitly.

And in the script of "QSelect" there were missing brackets
  // Fill the array, numbers from 1 to 144
  var arr1 = ;

Must be
  var arr1 = ;

I saw that they were missing in my script. Sometimes the HTML editor has its own ideas. Therefore its better to use the source code editor, which you select in your account (upper right corner).


Here I attach two sample surveys.

1. Using the library "PapaParse"
[url] www.papaparse.com/ [/url]
You need a csv file like this (here called "profiles.csv") uploaded to the "files" directory of the survey.

ProfileID,Field,Grade,Extracurricular,Semester
1,Mechanical Engineering,2.7 (Satisfactory) (Very Good),Student Parliament,3rd semester (Bachelor)
2,Mechanical Engineering,2.7 (Satisfactory) (Very Good),Student Parliament,5th semester (Bachelor)
3,Mechanical Engineering,2.7 (Satisfactory) (Very Good),Student Parliament,3rd semester (Master)
4,Mechanical Engineering,2.7 (Satisfactory) (Very Good),Sports Club,3rd semester (Bachelor)
...
98,Psychology,2.7 (Satisfactory),Student Parliament,5th semester (Bachelor)
99,Psychology,2.7 (Satisfactory),Student Parliament,3rd semester (Master)
100,Psychology,2.7 (Satisfactory),Sports Club,3rd semester (Bachelor)
...
142,Business Administration,2.7 (Satisfactory),Food Bank Volunteer,3rd semester (Bachelor)
143,Business Administration,2.7 (Satisfactory),Food Bank Volunteer,5th semester (Bachelor)
144,Business Administration,2.7 (Satisfactory),Food Bank Volunteer,3rd semester (Master)

All 144 combinations
As there are only twenty names we will use an array for them.

Now the only thing you have to do is to adapt the indices.
QSelect_1 is a string of characters representing the names
This is the first character, starting at position 0 (substr starts at 0) with a length of 1
    var y1='{substr(QSelect_1,0,1)}';
This is the second character, starting at position 1 with a length of 1
    var y2='{substr(QSelect_1,1,1)}';

The next tests will use the indices 2 and 3, then 4 and 5, and so on

QSelect_2 is a string of three digit numbers representing the profiles
This are the first three characters, starting at position 0 (substr starts at 0) with a length of 3
    var x1 = '{substr(QSelect_2,0,3)}';
This are the second three characters, starting at position 3 (substr starts at 0) with a length of 3
    var x2 = '{substr(QSelect_2,3,3)}';
The next tests will use the indices 6 and 9, then 12 and 15, and so on

This survey shows two ways to create the table.
  • With the library "tinyslider"
  • A "normal" HTML table.

Feel free to adapt the colors (all in the css part at the end of the source code resp. in the tinyslider tables as bootstrap declarations)
 

File Attachment:

File Name: limesurvey...Papa.lss
File Size:98.44 KB


2. The approach with ExpressionScript that I described already.
Again with different ways to create the table. (tinyslider, bootstrap table, generic)
Again you have to adapt the indices in eqSetx.
Have a look at the default answers of "Pool".
 

File Attachment:

File Name: limesurvey...8_ES.lss
File Size:225.39 KB


Joffm

BTW: Only such questions like "QSelect" that contain javascript are hidden either by "d-none" or as you see in the code by $('#question{QID}').hide();
All other questions hide by "Always hide this question"

Volunteers are not paid.
Not because they are worthless, but because they are priceless
Last edit: 2 weeks 3 days ago by Joffm.

Please Log in to join the conversation.

More
2 weeks 3 days ago - 2 weeks 3 days ago #273629 by baristurkdogan
Thanks Joffm, you're a magician! 🪄 Now it finally works!

I had a few further questions:

Q1: Name Restriction
  • As I said in the first post, I'd like to implement a name restriction so the respondents would not get shocked when they see the same name with different field of study, grade, semester, etc. Is it feasible to implement name restrictions in the current randomization approach—EITHER ensuring no profile with the same name appears more than once per respondent, OR ensuring that if a name repeats, the attribute levels are identical? Which option would be more feasible?

Q2: Weighted Randomization by Ethnicity
  • Would it be possible to apply weighted randomization? For example, let's say we want approximately 70% of profile pairs are mixed ethnicity (German vs. Turkish names) and 30% show same-ethnicity pairs (German vs. German names OR Turkish vs. Turkish names)? If so, what's the most practical approach?

Q3: Multilingual Survey (English + German)
  • If I add German language to my survey alongside English (so that it's easier to reach native German respondents), would the JavaScript and ExpressionScript logic (Pool, QSelect, eqSet equations, etc.) work identically in both languages, or would code changes be required?

Thanks again.
Last edit: 2 weeks 3 days ago by baristurkdogan. Reason: display issues

Please Log in to join the conversation.

More
2 weeks 2 days ago #273635 by Joffm
Hi,

Q1: Name Restriction

You see that all 20 names are randomised and used one by one. So no name will appear twice.
I hope you studied the script to understand what is done.

Q2: Weighted Randomization by Ethnicity

1. 70:30 is not possibly. That's mathematics. To get 70% mixed pairs you need 7 names. Now there are 3 names left. One pair and a single one.
So we generalise: Sometimes 80:20, sometimes 60:40

2. What thoughts are going through your mind about this? How can this be approached?
Currently, the 20 names are generated completely in random order.
How can 6 pairs be generated, each consisting of one name from A-J and one from K-T?
How can 4 pairs be generated, 2 consisting of both names from A-J and 2 consisting of both names from K-T?  

Q3: Multilingual Survey (English + German)

You have to distinguish two cases.
  1. You create the survey in one language at the start and enter all texts.
    Then you add a second language.
    All texts are copied to the second language tab.
    E.g. in the German tab there will be the English subquestion texts, answer options, etc. which you have to translate.
    But scripts, etc. alwayys stay the same
  2. You create the survey in two language at the start.
    You enter the text in one language.
    Now you have to copy all question texts with the scripts, etc. to the second language tab and translate subquestion text resp. answer options.

Volunteers are not paid.
Not because they are worthless, but because they are priceless

Please Log in to join the conversation.

More
2 weeks 1 day ago - 2 weeks 1 day ago #273641 by Joffm
To your "weighted randomisation".
Two solutions:
1. The one I mentioned already (50% 60:40,  50% 80:20)
This script
Code:
$(document).on('ready pjax:scriptcomplete',function(){
 
// Split the array (a1: German names, a2: Turkish names)
    var a1 = ["A","B","C","D","E","F","G","H","I","J"];
    var a2 = ["K","L","M","N","O","P","Q","R","S","T"];
 
// Shuffle both arrays
    a1 = shuffle(a1);
    a2 = shuffle(a2);
 
// Create a random number that returns 6 or 8
    number=6+2*Math.floor(Math.random() * 2);
 
// Create the empty final array
     var aFin = ;
 
// In a loop from 0 to the calculated number (6 or 8)
     for (var i = 0; i < number; i++) {
 
// Create a new temporary array
        var aTmp = ;
// where you push the German "name" and the Turkish "name" at position i
// You get "number" pairs of different ethnicity
        aTmp.push(a1[i]);
        aTmp.push(a2[i]);
 
// Shuffle this array that the order of "German" - "Turkish" is always different
        aTmp = shuffle(aTmp).join('');
// Push this array of two names into the final array
        aFin.push(aTmp);
     }
 
// Now you care about the rest
// In a loop from "number" to 10 with a step of 2
     for (var i = number; i < 10; i+=2) {
// Create a new temporary array
        var aTmp = ;
// where you push the German "name" at position i and the "name" at position i+1
        aTmp.push(a1[i]);
        aTmp.push(a1[i+1]);
        aTmp = shuffle(aTmp).join('');
        aFin.push(aTmp);
 
        var aTmp = ;
// here you push the Turkish "name" at position i and the "name" at position i+1
        aTmp.push(a2[i]);
        aTmp.push(a2[i+1]);
        aTmp = shuffle(aTmp).join('');
        aFin.push(aTmp);
     }
 
// Now the array aFin looks like [ BM, IR, SG, OA, CQ, KF, DE, JH, LN, PO ]
// Six pairs of different ethnicity, followed by two German pairs and two Turkish pairs
// This array again is shuffled
     aFin = shuffle(aFin).join('');
// and finally you get the desired string like JHCQIRDEPOKFSGLNBMOALN
     $('#question{QID} input[type="text"]:eq(0)').val(aFin);
//$('#question{QID}').hide();
});


The other more sophisticated way is to create a function that returns all possible distributions, but with an average of 70:30
I could imagine to create a random number from 1 to 100
If it is
1 - 2 : the distribution is 0 : 10 -> only equal ethnicities
3 - 7 : 2 : 8
8 - 17 : 4 : 6
18 - 47 : 6 : 4
48 - 77 : 8 : 2
78 - 100 : 10 : 0 -> only different ethnicities

You only need to adapt the creating of "number" (of course you are free to weight change the intervals, to get more 60:40, less 20:80, or whatever)

Code:
    var number=1+Math.floor(Math.random() * 100);
 
    if (number<3) { number=0; }
    else if (number<8) { number=2; }
    else if (number<18) { number=4; }
    else if (number<48) { number=6; }
    else if (number<78) { number=8; }
    else  { number=10; }




 

Volunteers are not paid.
Not because they are worthless, but because they are priceless
Last edit: 2 weeks 1 day ago by Joffm.

Please Log in to join the conversation.

More
2 weeks 1 day ago #273643 by baristurkdogan
 
Thanks for the responses and suggestions. I'll keep them in mind.

I understand that there's already name restriction embedded in the design. I also added German as a second language using the first method you mentioned.

For now, I activated the survey (the original version without weighted randomization) for some pretesting. You previously shared a picture showing how I'd be seeing the response statistics. However, I do not see any of the 10 conjoint choices when I export the results as a CSV file (except for the one that I shared as a screenshot under the name "Response stats sample"). What might have gone wrong? I also attached the current LSS file.

Thanks.
 

Please Log in to join the conversation.

More
1 week 6 days ago #273656 by baristurkdogan
Hello,

I'd really appreciate it if I could get some help about my last question on response statistics and their CSV exports. Because afterwards we plan to go live with the survey. 

Many thanks again!

Please Log in to join the conversation.

More
1 week 6 days ago #273658 by Joffm
Hi, I do not see any issue.
LimeSurvey response table
 
csv-Export opened in Excel
 
csv-Export opened in Wordpad
 

So everything is there, but you should use the correct settings (you seem to use the full question text instead of the codes)

BTW:
There is a small glitch in your table. The two buttons are not aligned equally.
 
In the third cell there is no "vertical-align:middle"

And in my opinion you shouldn't use the survey description (this ugly centered text) , but the welcome message (nicely left aligned).
Remember: The survey description is something like a subtitle (one line).

And avoid to copy/paste such texts, only in plain text mode. You always get some garbage of the other format.

Avoid to use dropdowns with only a few answer options. Dropdowns are really annoying for the respondent. He has to click once to open it, have a look which options are offered and click again to select it.
Better list(radio) or bootstrap buttons.
 
In the "country" question a dropdown is useful, either as a normal dropdown, or an "autocomplete" question (see Tutorial 2. )

Last: QInfo was used to show at least one question in this group. This because QSelect is hidden by javascript. This would usually result in a question with buttons where the question text and the answer options are hidden; but still there are the two buttons.
But you have this Info text "Instructions". This is a real question on the screen. Move it to GCalc and remove the "QInfo".

Joffm
 

Volunteers are not paid.
Not because they are worthless, but because they are priceless
The following user(s) said Thank You: baristurkdogan

Please Log in to join the conversation.

Moderators: tpartnerholch

Lime-years ahead

Online-surveys for every purse and purpose