This is actually slightly more complex than even that question asks.
I am asking parents to complete a survey about their child’s language and they tick each word their child knows. I would like to produce a word cloud from the words their child knows. It can either a) just have a random set of random sized words from among the words their child knows b) have a set of words that is in proportion to the score for the category that word comes from (e.g. if their child scored 10 on animal words the word “dog” would be randomly chosen from that category but then if they only scored 2 on food words the word “cheese” would be smaller). Currently the word items are numeric (so I know this isn’t ideal for passing to a word cloud) and I know Qualtrics can display live reports but I can’t work out how it would display a live word cloud OR how it would display just the report from that one parent’s data. The individual word clouds (especially if I can then work out how to allow parents to save them to their devices) would be really fun for the parents as a snapshot of what their child could say at that age.
Best answer by vgayraud
Hi,
I’ve done something similar in the past using jQCloud. The way I had set up things was with multiple choices multiple answers questions for each category, and base the weight of a word on the number of items selected in its category. I don’t know if it fits your use case but it can be a good starting point.
Here’s an example:
Javascript to add to your results question (configure questionData with your IDs and don’t forget to load jQuery in your header if you’re using the new survey taking experience):
Qualtrics.SurveyEngine.addOnReady(function () {
// Load jQCloud function loadResource(type, url) { return new Promise(function (resolve, reject) { var el; if (type === "css") { el = document.createElement("link"); el.rel = "stylesheet"; el.href = url; } else { el = document.createElement("script"); el.src = url; } el.onload = resolve; el.onerror = reject; document.head.appendChild(el); }); }
// Get data var groups = []; Object.keys(questionData).forEach(function (qid, idx) { var raw = questionData[qid]; console.log("Raw data from", qid, ":", raw); var list = raw ? raw.split(",").map(s => s.trim()).filter(Boolean) : []; groups.push({ id: qid, words: list, count: list.length, color: colors[idx % colors.length] }); });
var totalWords = groups.reduce((a, g) => a + g.count, 0); if (totalWords === 0) { console.warn("No words selected across questions. Exiting."); return; }
// Weights groups.forEach(g => g.weightRaw = g.count / totalWords); var rawMin = Math.min(...groups.map(g => g.weightRaw)); var rawMax = Math.max(...groups.map(g => g.weightRaw)); var steps = 10;
I’ve done something similar in the past using jQCloud. The way I had set up things was with multiple choices multiple answers questions for each category, and base the weight of a word on the number of items selected in its category. I don’t know if it fits your use case but it can be a good starting point.
Here’s an example:
Javascript to add to your results question (configure questionData with your IDs and don’t forget to load jQuery in your header if you’re using the new survey taking experience):
Qualtrics.SurveyEngine.addOnReady(function () {
// Load jQCloud function loadResource(type, url) { return new Promise(function (resolve, reject) { var el; if (type === "css") { el = document.createElement("link"); el.rel = "stylesheet"; el.href = url; } else { el = document.createElement("script"); el.src = url; } el.onload = resolve; el.onerror = reject; document.head.appendChild(el); }); }
// Get data var groups = []; Object.keys(questionData).forEach(function (qid, idx) { var raw = questionData[qid]; console.log("Raw data from", qid, ":", raw); var list = raw ? raw.split(",").map(s => s.trim()).filter(Boolean) : []; groups.push({ id: qid, words: list, count: list.length, color: colors[idx % colors.length] }); });
var totalWords = groups.reduce((a, g) => a + g.count, 0); if (totalWords === 0) { console.warn("No words selected across questions. Exiting."); return; }
// Weights groups.forEach(g => g.weightRaw = g.count / totalWords); var rawMin = Math.min(...groups.map(g => g.weightRaw)); var rawMax = Math.max(...groups.map(g => g.weightRaw)); var steps = 10;
That looks absolutely perfect - I’m going to have quite a few more words that might potentially go into the word cloud (as the parent can select out of over 500 words their child might know) so I may try and randomly choose a few words they know, out of each category.
Hi @vgayraud I have a couple more questions, though astonishingly this works almost immediately. Here is my result from my first two categories of words (I have about 15).
I had originally set up a Score for each choice section - as I couldn’t see how to pipe the Count from the question itself, but that seems to be something hidden that I can use without knowing how to use it. I have worked out why the animal noises are oddly formatted (it’s to do with how the questions were set up, and I’m removing the odd formatting from the questions). I also accidentally put an extra $ in front of the Animal Names category in the JS so that is where the $ came from.
I would now like to increase the number of categories (this shouldn’t be hard) but also to randomly select just a few words in each category. Here are 5 categories out of the 15. I am not sure why the wordcloud is displaying over the text (I could put the instructions for saving the wordcloud on the previous page, but I’d rather put the title of the wordcloud on the same page: the beginning of the title is cut off in this screenshot, but it was hard to read.)
Also, there are attention checks in the word list and I don’t want those to display. I can remove them from the scoring by adjusting the items that add up to each category score but I don’t want “please select this item” to appear in the word cloud. However, I DO still want it to appear in the list of words in the same format (so I can’t make it be a separate word to tick in a separate question).
Would you be able to suggest any changes that can help me with this?
This is untested, but you could try to add 2 configuration variables (under the colors one, say).
var validationChecks = ['validation check 1', 'validation check 2']; var maxWords = 5;
And modify the line where you define the lists:
var list = raw ? raw.split(",").map(s => s.trim()).filter(s => s && !validationChecks.includes(s)).sort(() => Math.random() - 0.5).slice(0, maxWords) : [];
This would remove any attention check you define before randomly selecting up to maxWords words for each category. Note that the word weights will now be based on the number of randomly selected words, and not on the number of words selected by the respondent.
For your title problem, it’s hard to say without seeing your question html code but I suspect you added it inside the wordCloudContainer. If so, try putting it outside.
var validationChecks = ['select this one to show you are reading', 'please tick this to show you are reading', 'choose this to show you are reading'];
var maxWords = 5;
;
I have changed the list section to
var list = raw ? raw.split(",").map(s => s.trim()).filter(s => s && !validationChecks.includes(s)).sort(() => Math.random() - 0.5).slice(0, maxWords) : []; groups.push({ id: qid, words: list, count: list.length, color: colors[idx % colors.length] }); });
It eliminates the attention checks and also does not display too many words in each category. I still haven’t seen what happens when I check words in every category (there are about 15 categories, if it looks too busy I will just make the maximum number of words lower). I also haven’t increased the number of categories higher than the number of colours you have specified, maybe it will implode at that point but I guess I can add more colours!
My layout problem persists but oddly it looks lovely in Mobile view - nice spacing between the title “these are some words your child CHILD’S NAME can say on DATE”, no overlap.
In the desktop view, the previous text (instructions of what to do with the wordcloud) and the title text (these are some words….) are separate questions, because I thought that would help with overlap but it doesn’t. Here’s the HTML for the title text:
Words that ${q://QID1131/ChoiceTextEntryValue} can say on ${date://CurrentDate/PT}
And here’s the HTML for the wordcloud question:
(I just put in a space so it wouldn’t keep telling me to add a question.)
However, I now moved the title for the wordcloud back to the same question and it is looking better EXCEPT that my forward and back arrows are now over the wordcloud, which I suspect is a corporate/style issue so I shall fiddle around with that now.
Thanks so much for your help - this proved to be a lot simpler than I thought, and hopefully my parent-participants will be charmed and delighted with their toddler word clouds!
OK - I’m back. The word cloud is working but the positioning problem with the wordcloud appearing over other text… isn’t just confined to the page the wordcloud is on.
When I move to the next page it appears again! And again! And again!
I could, eventually, make the wordcloud appear on the very last page (after a lot of other questions) rather than immediately after the vocabulary questions but that would still mean the final thank-you page had a stray wordcloud. For some participants a code must be collected on this page so I don’t want them to miss the code if it’s got a wordcloud over it!
I tried changing to position: fixed or position: static but this does not solve the problem - the wordcloud is still over other elements of the page and still on every subsequent page.