Welcome to the LimeSurvey Community Forum

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

Adaptive MaxDiff plugin for LimeSurvey 6 (experimental)

More
10 hours 44 minutes ago #273173 by kaitumisuuringute.keskus

I've put together an experimental Adaptive MaxDiff plugin for LimeSurvey 6 and pushed it to GitHub:

github.com/kaitumisuuringute-keskus/limesurvey-adaptive-maxdiff

It takes a normal `T` (Long free text) question and turns it into a MaxDiff / Best–Worst block: respondents see small sets of items, pick “best” and “worst”, and the plugin adapts which items appear next based on their previous answers. All per-respondent state is stored in a plugin table and, at the end, the question’s answer field just contains a JSON blob with the full history (so it exports through LimeSurvey like any other answer).

Items can come either from a label set (codes as IDs, titles as texts) or from inline JSON. Best/Worst labels are multilingual (LS i18n attributes), and for buttons the plugin uses LimeSurvey’s own translations.

This is very much a v0.1. The adaptive logic is a simple heuristic (push best up, worst down; favor under-shown/uncertain/mid-utility items), not an academically “optimal” design. The AJAX endpoint currently uses `newUnsecureRequest`, and most of the validation (e.g. minimum number of tasks) is enforced client-side. It’s fine for controlled use and prototyping, but I wouldn’t call it security-hardened or foolproof yet.

README in the repo has the details: install steps, attribute list, JSON schema, and a roadmap for possible upgrades (better algorithms, server-side validation, safer API, export helpers).

If anyone else is trying to do MaxDiff in LimeSurvey and wants to kick the tyres, I'd be interested in feedback, bug reports, or ideas on how to integrate this more cleanly with LS’s question system.
 
The following user(s) said Thank You: DenisChenu

Please Log in to join the conversation.

More
6 hours 45 minutes ago #273174 by DenisChenu
Yeah, great !!!

Just some questions and remark 

- Why did you choose a long text question and a json ? Why not an array question type ?
- Why do you need an extra table (maybe linked to question 1, analysis system ?)
- Can we disable saving and using the extra table ? Since data are already in response
- About source ; it can be great to have source from a single choice question inside the survey (I see some issue with label set)

Assistance on LimeSurvey forum and LimeSurvey core development are on my free time.
I'm not a LimeSurvey GmbH member. - Professional support - Plugins, theme and development .
I don't answer to private message.

Please Log in to join the conversation.

More
5 hours 28 minutes ago #273175 by kaitumisuuringute.keskus

Why did you choose a long text question and a json ? Why not an array question type ?

Because the adaptive MaxDiff question doesn’t have a fixed, simple answer schema.

Each respondent sees a different sequence of sets, and for each task I need to store:
  1. which items were shown, and
  2. which item was Best and which was Worst.

In LimeSurvey the response table schema is fixed at activation (afaik). An array type would require me to pre-declare some huge fixed grid of subquestions (task1_item1_best, task1_item1_worst, … up to some arbitrary max), most of which would be empty for most respondents. A single long-text field with JSON lets me store the full per-respondent history (all tasks, items and choices) without fighting the schema.

Conceptually, yes, you could abuse dual-scale arrays or multiple short texts, but for an adaptive design with variable number of tasks a single JSON blob is the least fragile option. If there’s a core type that gives a real advantage over T here, I’m open to changing the base type.

Why do you need an extra table (maybe linked to question 1, analysis system ?)

The plugin needs per-respondent algorithm state, not just the final answers. That includes utilities, exposure counts, pending task, history, etc.

I could in theory reconstruct everything from the JSON answer field on every request, or try to keep it in PHP session, but both have issues: sessions expire / get lost, and repeatedly decoding large JSON blobs for every request is not great.

A small plugin table keyed by (survey_id, qid, block_id, respondent_key) is the most robust way to keep the adaptive state: it survives session changes, is easy to inspect for diagnostics, and will also be needed if I plug in more complex algorithms (bandit style, global priors, etc.).

Can we disable saving and using the extra table ? Since data are already in response

Not in this version. In principle you could run a “no extra table” mode where the client sends the full JSON state back to the server on every step and the server just updates and returns it without persisting anything.

I haven’t implemented that because you then either:
  1. fully trust the client’s JSON (easy to spoof), or
  2. re-validate and re-compute a lot on every call anyway.
The dedicated table keeps the logic simple and verifiable. That said, a "reduced mode" that only uses the answer JSON and no plugin table is technically possible, just with weaker guarantees and more trust in the browser.

About source ; it can be great to have source from a single choice question inside the survey (I see some issue with label set)

Yeah, the label set I haven't actually tested much yet. It should, however, be a good choice since it's the standard "globally stored answer options" in LS. In my current first experiment I'm running it with inline JSON, not a label set. What problems could label sets introduce?



I’m running the first larger test (1k+ respondents) with this setup right now. After that I’ll have real data to check both the question type choice and the extra table design, and I can share results if people are interested.

Please Log in to join the conversation.

More
5 hours 19 minutes ago #273176 by DenisChenu
OK ! I think I didn't have all the internal concept here !

About source : I understand, you use JSON source, but some of your user say it's complex ?

Assistance on LimeSurvey forum and LimeSurvey core development are on my free time.
I'm not a LimeSurvey GmbH member. - Professional support - Plugins, theme and development .
I don't answer to private message.

Please Log in to join the conversation.

More
5 hours 12 minutes ago #273177 by kaitumisuuringute.keskus
Yeah, JSON is annoying and it breaks the normal LimeSurvey authoring flow. I’m planning to look into turning it into a proper answer editor inside the UI (add/delete/reorder items like a regular answer list). I just need to dig deeper into how much of that LS exposes in the question internals before I can say how feasible it is.

Please Log in to join the conversation.

Moderators: holchtpartner

Lime-years ahead

Online-surveys for every purse and purpose