<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>surveydown.org</title>
<link>https://www.surveydown.org/blog/</link>
<atom:link href="https://www.surveydown.org/blog/index.xml" rel="self" type="application/rss+xml"/>
<description></description>
<image>
<url>https://www.surveydown.org/images/logo.ico</url>
<title>surveydown.org</title>
<link>https://www.surveydown.org/blog/</link>
</image>
<generator>quarto-1.9.37</generator>
<lastBuildDate>Fri, 21 Nov 2025 00:00:00 GMT</lastBuildDate>
<item>
  <title>Announcing surveydown v1.0.0!</title>
  <dc:creator>John Paul Helveston</dc:creator>
  <dc:creator>Pingfan Hu</dc:creator>
  <link>https://www.surveydown.org/blog/2025-11-21-announcing-surveydown-version-1/</link>
  <description><![CDATA[ <section id="installation" class="level2"><h2 class="anchored" data-anchor-id="installation">Installation</h2>
<p>Verion 1.0.0 is coming to CRAN soon, but in the meantime you can upgrade to it by installing it from GitHub:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># install.packages("pak")</span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pak</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pak</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"surveydown-dev/surveydown"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>Now, let’s check out the new features!</p>
</section><section id="yaml-settings" class="level2"><h2 class="anchored" data-anchor-id="yaml-settings">YAML settings</h2>
<p>A YAML header is used in every <code>.qmd</code> file as metadata to define page behavior. The <code>survey.qmd</code> file in each <code>surveydown</code> survey also relies on the YAML header, but we’ve made some significant changes to improve the experience.</p>
<p><strong>YAML omission:</strong> First, you no longer need to include any YAML header at all now as <code>surveydown</code> now auto-loads the following:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb2-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> html</span></span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">echo</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">false</span></span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">warning</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">false</span></span>
<span id="cb2-5"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div></div>
<p>This used to be the standard YAML header in <code>survey.qmd</code>, but now if you leave it out, these settings will be used by default.</p>
<p><strong>New YAML experience:</strong> An empty YAML is fine if you want to use all default settings, so your <code>survey.qmd</code> file can start directly with your library calls and survey content:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb3-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">library(surveydown)</span></span>
<span id="cb3-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">library(other_packages)</span></span>
<span id="cb3-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb3-5"></span>
<span id="cb3-6">Survey content...</span></code></pre></div></div>
</div>
<p><strong>YAML settings:</strong> We have also expanded the YAML header to include all other survey settings to customize your survey behavior. Below is a full list of all possible YAML settings with their default values, including <strong>theme</strong>, <strong>survey</strong>, and <strong>system message</strong> settings. The comprehensive list of settings used in any one survey are generated in your <code>_survey/settings.yml</code> file of any <code>surveydown</code> survey project.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb4-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb4-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme-settings</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> default</span></span>
<span id="cb4-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">barposition</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> top</span></span>
<span id="cb4-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">footer-left</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span></span>
<span id="cb4-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">footer-center</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span></span>
<span id="cb4-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">footer-right</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span></span>
<span id="cb4-8"></span>
<span id="cb4-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">survey-settings</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">show-previous</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">no</span></span>
<span id="cb4-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">use-cookies</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">no</span></span>
<span id="cb4-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">auto-scroll</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">no</span></span>
<span id="cb4-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rate-survey</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">no</span></span>
<span id="cb4-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all-required</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">no</span></span>
<span id="cb4-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">start-page</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> your_first_page</span></span>
<span id="cb4-16"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">system-language</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> en</span></span>
<span id="cb4-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">highlight-unanswered</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">yes</span></span>
<span id="cb4-18"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">highlight-color</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> gray</span></span>
<span id="cb4-19"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">capture-metadata</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">yes</span></span>
<span id="cb4-20"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">required</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[]</span></span>
<span id="cb4-21"></span>
<span id="cb4-22"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">system-messages</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-23"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cancel</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Cancel</span></span>
<span id="cb4-24"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">confirm-exit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Confirm Exit</span></span>
<span id="cb4-25"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sure-exit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Are you sure you want to exit the survey?</span></span>
<span id="cb4-26"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">submit-exit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Submit and Exit</span></span>
<span id="cb4-27"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">warning</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Warning</span></span>
<span id="cb4-28"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">required</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Please answer all required questions before proceeding.</span></span>
<span id="cb4-29"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rating-title</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Before you go...</span></span>
<span id="cb4-30"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rating-text</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Rate your survey experience:'</span></span>
<span id="cb4-31"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rating-scale</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> from 1-poor to 5-excellent</span></span>
<span id="cb4-32"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">previous</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Previous</span></span>
<span id="cb4-33"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">next</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Next</span></span>
<span id="cb4-34"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Exit Survey</span></span>
<span id="cb4-35"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">close-tab</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Please close this tab manually to exit the survey.</span></span>
<span id="cb4-36"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">choose-option</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Choose an option...</span></span>
<span id="cb4-37"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">click</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Click here</span></span>
<span id="cb4-38"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">redirect</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Redirecting in</span></span>
<span id="cb4-39"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seconds</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> seconds</span></span>
<span id="cb4-40"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">new-tab</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Opens in a new tab</span></span>
<span id="cb4-41"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">redirect-error</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Error: This text won't trigger any redirection..."</span></span>
<span id="cb4-42"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div></div>
<p>You can customize any of them in <code>survey.qmd</code> to fit your survey needs. For example, say you want to <strong>enable cookies</strong>, you can have these YAML settings in your <code>survey.qmd</code> file (cookies are on by default):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb5-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">survey-settings</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb5-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">use-cookies</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">yes</span></span>
<span id="cb5-4"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div></div>
<p>Note also the <code>system-messages</code> category. Here you can customize the text of all system messages used in your survey. For example, to change the “Next” button label to “Continue”, you can do this:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb6-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb6-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">system-messages</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">next</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Continue</span></span>
<span id="cb6-4"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div></div>
<p>This used to be handled in a separate <code>translations.yml</code> file, but now they’re all consolidated into the YAML header for easier access.</p>
</section><section id="previous-button-support" class="level2"><h2 class="anchored" data-anchor-id="previous-button-support">Previous Button Support</h2>
<p>One of the most requested features is finally here: <strong>previous buttons</strong>! Survey respondents can now navigate backwards through your survey, and you have full control over whether to enable this feature globally or on a per-page basis.</p>
<p><strong>Global setting:</strong> By default, previous buttons are <strong>not</strong> enabled, but you can enable them globally by changing the YAML header setting in the <code>survey.qmd</code> file:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb7-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb7-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">survey-settings</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb7-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">show-previous</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb7-4"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div></div>
<p><strong>Page-Level override:</strong> You can override the global setting on specific pages using the newly introduced <code>sd_nav()</code> function in your <code>survey.qmd</code> file:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Enable previous button on a page</span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_nav</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>show_previous <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Disable previous button on a page</span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_nav</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>show_previous <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>Here are examples of previous button being enabled and disabled:</p>
<center>
<img src="https://www.surveydown.org/blog/2025-11-21-announcing-surveydown-version-1/images/previous_off.png" style="max-width: 700px; width: 100%;"><p>
<em>Previous button disabled</em>
</p>
</center>
<p><br></p>
<center>
<img src="https://www.surveydown.org/blog/2025-11-21-announcing-surveydown-version-1/images/previous_on.png" style="max-width: 700px; width: 100%;"><p>
<em>Previous button enabled</em>
</p>
</center>
</section><section id="auto-page-navigation" class="level2"><h2 class="anchored" data-anchor-id="auto-page-navigation">Auto Page Navigation</h2>
<p>One of our favorite new additions is auto-injecting page navigation. In previous versions of <code>surveydown</code>, you needed to add <code>sd_next()</code> on each page to insert next buttons. But now navigation buttons are auto injected at the end of each page unless you call <code>sd_nav()</code> or <code>sd_close()</code> on that page, which will override the global settings.</p>
<p>This means survey page definition can be as simple as:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> page_1</span>
<span id="cb9-2"></span>
<span id="cb9-3">Page <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> content...</span>
<span id="cb9-4"></span>
<span id="cb9-5"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> page_2</span>
<span id="cb9-6"></span>
<span id="cb9-7">Page <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> content...</span>
<span id="cb9-8"></span>
<span id="cb9-9"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> page_3</span>
<span id="cb9-10"></span>
<span id="cb9-11">Page <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span> content...</span></code></pre></div></div>
</div>
<p>No navigation code needed - <code>surveydown</code> handles it for you!</p>
<div class="callout callout-style-default callout-tip callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>The auto nav injection is equivalent to having <code>sd_nav()</code> at the end of a page with a succeeding page. If you manually call <code>sd_nav()</code> or <code>sd_close()</code>, the auto injection will be overridden.</p>
</div>
</div>
<p><strong>Manual navigation control</strong>: Use <code>sd_nav()</code> or <code>sd_close()</code> to customize navigation.</p>
<p>The new <code>sd_nav()</code> function replaces the old <code>sd_next()</code>, providing a unified interface for both previous and next buttons.</p>
<p>In most cases, calling <code>sd_nav()</code> with empty parameters will suffice, as it defaults to showing the navigation buttons based on your global settings.</p>
<p><code>sd_nav()</code> has the following arguments:</p>
<ul>
<li>
<code>page_next</code>: Which page to go to next? (defaults to the next page in order)</li>
<li>
<code>label_previous</code>: Override previous button label (defaults to the system message “Previous”)</li>
<li>
<code>label_next</code>: Override next button label (defaults to the system message “Next”)</li>
<li>
<code>show_previous</code>: Show previous button? (defaults to the global setting)</li>
<li>
<code>show_next</code>: Show next button? (defaults to the global setting)</li>
</ul>
<p>Likewise, <code>sd_close()</code> supports both previous and next buttons with the following arguments:</p>
<ul>
<li>
<code>label_close</code>: Label on the close page buttons (defaults to the system message “Close”)</li>
<li>
<code>label_previous</code>: Override previous button label (defaults to the system message “Previous”)</li>
<li>
<code>show_previous</code>: Show previous button? (defaults to the global setting)</li>
</ul></section><section id="sd_question-enhancements" class="level2"><h2 class="anchored" data-anchor-id="sd_question-enhancements">
<code>sd_question()</code> Enhancements</h2>
<p>Since <code>surveydown</code> is built on top of shiny, we originally used the singular word <code>option</code> to define multiple-choice options in <code>sd_question()</code> (this is what shiny uses). But this can be confusing, since most of the time you want to provide multiple <code>options</code> (plural).</p>
<p>To address this, now <strong>both <code>option</code> and <code>options</code> are supported</strong> for <code>sd_question()</code> when using multiple-choice type questions, such as <code>mc</code>, <code>mc_buttons</code>, etc.</p>
<p><strong>Auto label to value conversion</strong>: When defining <code>option</code> or <code>options</code>, the traditional way to define options is the pattern <code>label = value</code>, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"favorite_color"</span>,</span>
<span>  type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mc"</span>,</span>
<span>  label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What's your favorite color?"</span>,</span>
<span>  options <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Light Blue"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"light_blue"</span>,</span>
<span>    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dark Green"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dark_green"</span>,</span>
<span>    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bright Red"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bright_red"</span></span>
<span>  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>But in case you forget this pattern, you can now just provide a single vector of labels like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"favorite_color"</span>,</span>
<span>  type <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mc"</span>,</span>
<span>  label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What's your favorite color?"</span>,</span>
<span>  options <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Light Blue"</span>,</span>
<span>    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dark Green"</span>,</span>
<span>    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bright Red"</span></span>
<span>  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>In this case, the value stored in the data will be automatically converted to snake case. In this example, the above question will store the following values in the database:</p>
<table class="caption-top table">
<thead><tr class="header">
<th>Display Label</th>
<th>Database Value</th>
</tr></thead>
<tbody>
<tr class="odd">
<td>Light Blue</td>
<td><code>light_blue</code></td>
</tr>
<tr class="even">
<td>Dark Green</td>
<td><code>dark_green</code></td>
</tr>
<tr class="odd">
<td>Bright Red</td>
<td><code>bright_red</code></td>
</tr>
</tbody>
</table>
<div class="callout callout-style-default callout-caution callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Caution
</div>
</div>
<div class="callout-body-container callout-body">
<p>This snake case conversion is <strong>removed</strong> after <code>v1.1.0</code>, in which if you provide a single vector of labels, the values stored in the database will be exactly the same as the labels shown to respondents.</p>
</div>
</div>
</section><section id="whats-next" class="level2"><h2 class="anchored" data-anchor-id="whats-next">What’s Next?</h2>
<p>This <code>v1.0.0</code> release marks a major milestone for <code>surveydown</code>, but we’re not stopping here. We have exciting features planned for future releases. Stay tuned!</p>
<p>As always, we welcome your feedback and contributions. If you encounter any issues or have suggestions, please <a href="https://github.com/surveydown-dev/surveydown/issues">open an issue for the package</a>, <a href="https://github.com/orgs/surveydown-dev/discussions">create a discussion in our organization</a>, or contribute directly via pull requests.</p>
<p>Happy surveying!</p>


</section><a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>package</category>
  <category>feature</category>
  <guid>https://www.surveydown.org/blog/2025-11-21-announcing-surveydown-version-1/</guid>
  <pubDate>Fri, 21 Nov 2025 00:00:00 GMT</pubDate>
  <media:content url="https://www.surveydown.org/blog/2025-11-21-announcing-surveydown-version-1/banner.png" medium="image" type="image/png" height="96" width="144"/>
</item>
<item>
  <title>Introducing Shorthand Page Syntax in v0.14.0</title>
  <dc:creator>John Paul Helveston</dc:creator>
  <link>https://www.surveydown.org/blog/2025-11-15-shorthand-page-syntax/</link>
  <description><![CDATA[ <p>We are excited to announce a significant improvement to the surveydown developer experience in package version 0.14.0: <strong>shorthand page syntax</strong>. This new syntax makes defining pages in your surveys dramatically cleaner and easier to read, while maintaining full backward compatibility with the existing fence syntax.</p>
<section id="the-problem-verbose-fence-syntax" class="level2"><h2 class="anchored" data-anchor-id="the-problem-verbose-fence-syntax">The Problem: Verbose Fence Syntax</h2>
<p>Since the beginning, surveydown has used Quarto’s fence syntax (three colons <code>:::</code>) to define pages. While this approach works well and leverages familiar Quarto conventions, it requires explicit opening and closing tags for every page:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>welcome}</span>
<span id="cb1-2"></span>
<span id="cb1-3">Welcome to our survey<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span></span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:::</span></span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>demographics}</span>
<span id="cb1-8"></span>
<span id="cb1-9">Please tell us about yourself.</span>
<span id="cb1-10"></span>
<span id="cb1-11"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span>
<span id="cb1-12"></span>
<span id="cb1-13"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>questions}</span>
<span id="cb1-14"></span>
<span id="cb1-15">Now <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> the main questions...</span>
<span id="cb1-16"></span>
<span id="cb1-17"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span></code></pre></div></div>
</div>
<p>As your surveys grow, these closing <code>:::</code> tags add visual clutter and make it harder to see where one page ends and another begins. You also need to remember to close every page - forgetting a closing fence can cause parsing errors.</p>
</section><section id="the-solution-shorthand-syntax" class="level2"><h2 class="anchored" data-anchor-id="the-solution-shorthand-syntax">The Solution: Shorthand Syntax</h2>
<p>With surveydown package version 0.14.0, we’re introducing a new <strong>shorthand syntax</strong> that eliminates the need for closing tags. Instead, you simply use three dashes <code>---</code> followed by the page ID:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> welcome</span>
<span id="cb2-2"></span>
<span id="cb2-3">Welcome to our survey<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span></span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> demographics</span>
<span id="cb2-6"></span>
<span id="cb2-7">Please tell us about yourself.</span>
<span id="cb2-8"></span>
<span id="cb2-9"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> questions</span>
<span id="cb2-10"></span>
<span id="cb2-11">Now <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> the main questions...</span></code></pre></div></div>
</div>
<p>That’s it! Each new page delimiter automatically closes the previous page, so there’s no need to track opening and closing tags. The syntax is cleaner, more concise, and easier to scan visually.</p>
<p>The shorthand syntax offers several advantages:</p>
<ol type="1">
<li>
<strong>Cleaner code</strong>: Eliminates visual clutter from closing tags</li>
<li>
<strong>Easier to scan</strong>: Page delimiters stand out clearly, making survey structure obvious</li>
<li>
<strong>Less typing</strong>: Fewer characters to type means faster survey development</li>
<li>
<strong>Fewer errors</strong>: No need to remember closing tags - can’t forget what doesn’t exist!</li>
<li>
<strong>Better git diffs</strong>: When you add or modify pages, diffs are cleaner without closing tag changes</li>
</ol></section><section id="example" class="level2"><h2 class="anchored" data-anchor-id="example">Example</h2>
<p>Let’s look at another survey example to see the improvement. Here’s the same survey written both ways:</p>
<div class="tabset-margin-container"></div><div class="panel-tabset">
<ul class="nav nav-tabs">
<li class="nav-item"><a class="nav-link active" id="tabset-1-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-1" aria-controls="tabset-1-1" aria-selected="true" href="">Fence Syntax (Old)</a></li>
<li class="nav-item"><a class="nav-link" id="tabset-1-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-2" aria-controls="tabset-1-2" aria-selected="false" href="">Shorthand Syntax (New)</a></li>
</ul>
<div class="tab-content">
<div id="tabset-1-1" class="tab-pane active" aria-labelledby="tabset-1-1-tab">
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb3-2">format<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> html</span>
<span id="cb3-3">echo<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> false</span>
<span id="cb3-4"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb3-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">library(surveydown)</span></span>
<span id="cb3-8"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb3-9"></span>
<span id="cb3-10"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>welcome}</span>
<span id="cb3-11"></span>
<span id="cb3-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Welcome!</span></span>
<span id="cb3-13"></span>
<span id="cb3-14">Thank you <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> participating <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> our study.</span>
<span id="cb3-15"></span>
<span id="cb3-16"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb3-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_next()</span></span>
<span id="cb3-18"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb3-19"></span>
<span id="cb3-20"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span>
<span id="cb3-21"></span>
<span id="cb3-22"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>consent}</span>
<span id="cb3-23"></span>
<span id="cb3-24"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Informed Consent</span></span>
<span id="cb3-25"></span>
<span id="cb3-26">Please read the following information carefully...</span>
<span id="cb3-27"></span>
<span id="cb3-28"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb3-29"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_question(</span></span>
<span id="cb3-30"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  type = 'mc',</span></span>
<span id="cb3-31"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  id = 'consent',</span></span>
<span id="cb3-32"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  label = "Do you consent to participate?",</span></span>
<span id="cb3-33"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  option = c(</span></span>
<span id="cb3-34"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Yes, I consent' = 'yes',</span></span>
<span id="cb3-35"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'No, I decline' = 'no'</span></span>
<span id="cb3-36"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  )</span></span>
<span id="cb3-37"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-38"></span>
<span id="cb3-39"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_next()</span></span>
<span id="cb3-40"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb3-41"></span>
<span id="cb3-42"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span>
<span id="cb3-43"></span>
<span id="cb3-44"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>demographics}</span>
<span id="cb3-45"></span>
<span id="cb3-46"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Demographics</span></span>
<span id="cb3-47"></span>
<span id="cb3-48"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb3-49"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_question(</span></span>
<span id="cb3-50"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  type = 'numeric',</span></span>
<span id="cb3-51"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  id = 'age',</span></span>
<span id="cb3-52"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  label = "What is your age?"</span></span>
<span id="cb3-53"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-54"></span>
<span id="cb3-55"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_question(</span></span>
<span id="cb3-56"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  type = 'mc',</span></span>
<span id="cb3-57"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  id = 'education',</span></span>
<span id="cb3-58"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  label = "What is your highest level of education?",</span></span>
<span id="cb3-59"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  option = c(</span></span>
<span id="cb3-60"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'High school' = 'hs',</span></span>
<span id="cb3-61"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Bachelor</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\'</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s degree' = 'ba',</span></span>
<span id="cb3-62"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Graduate degree' = 'grad'</span></span>
<span id="cb3-63"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  )</span></span>
<span id="cb3-64"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-65"></span>
<span id="cb3-66"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_next()</span></span>
<span id="cb3-67"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb3-68"></span>
<span id="cb3-69"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span>
<span id="cb3-70"></span>
<span id="cb3-71"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>survey_questions}</span>
<span id="cb3-72"></span>
<span id="cb3-73"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Main Questions</span></span>
<span id="cb3-74"></span>
<span id="cb3-75"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb3-76"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_question(</span></span>
<span id="cb3-77"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  type = 'mc',</span></span>
<span id="cb3-78"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  id = 'satisfaction',</span></span>
<span id="cb3-79"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  label = "How satisfied are you with our product?",</span></span>
<span id="cb3-80"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  option = c(</span></span>
<span id="cb3-81"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Very satisfied' = '5',</span></span>
<span id="cb3-82"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Satisfied' = '4',</span></span>
<span id="cb3-83"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Neutral' = '3',</span></span>
<span id="cb3-84"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Dissatisfied' = '2',</span></span>
<span id="cb3-85"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Very dissatisfied' = '1'</span></span>
<span id="cb3-86"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  )</span></span>
<span id="cb3-87"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-88"></span>
<span id="cb3-89"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_next()</span></span>
<span id="cb3-90"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb3-91"></span>
<span id="cb3-92"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span>
<span id="cb3-93"></span>
<span id="cb3-94"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>end}</span>
<span id="cb3-95"></span>
<span id="cb3-96"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Thank You!</span></span>
<span id="cb3-97"></span>
<span id="cb3-98">Your responses have been recorded. You may now close this window.</span>
<span id="cb3-99"></span>
<span id="cb3-100"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb3-101"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_close()</span></span>
<span id="cb3-102"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb3-103"></span>
<span id="cb3-104"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span></code></pre></div></div>
</div>
</div>
<div id="tabset-1-2" class="tab-pane" aria-labelledby="tabset-1-2-tab">
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb4-2">format<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> html</span>
<span id="cb4-3">echo<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> false</span>
<span id="cb4-4"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb4-5"></span>
<span id="cb4-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb4-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">library(surveydown)</span></span>
<span id="cb4-8"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb4-9"></span>
<span id="cb4-10"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> welcome</span>
<span id="cb4-11"></span>
<span id="cb4-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Welcome!</span></span>
<span id="cb4-13"></span>
<span id="cb4-14">Thank you <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> participating <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> our study.</span>
<span id="cb4-15"></span>
<span id="cb4-16"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb4-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_next()</span></span>
<span id="cb4-18"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb4-19"></span>
<span id="cb4-20"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> consent</span>
<span id="cb4-21"></span>
<span id="cb4-22"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Informed Consent</span></span>
<span id="cb4-23"></span>
<span id="cb4-24">Please read the following information carefully...</span>
<span id="cb4-25"></span>
<span id="cb4-26"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb4-27"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_question(</span></span>
<span id="cb4-28"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  type = 'mc',</span></span>
<span id="cb4-29"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  id = 'consent',</span></span>
<span id="cb4-30"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  label = "Do you consent to participate?",</span></span>
<span id="cb4-31"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  option = c(</span></span>
<span id="cb4-32"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Yes, I consent' = 'yes',</span></span>
<span id="cb4-33"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'No, I decline' = 'no'</span></span>
<span id="cb4-34"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  )</span></span>
<span id="cb4-35"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-36"></span>
<span id="cb4-37"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_next()</span></span>
<span id="cb4-38"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb4-39"></span>
<span id="cb4-40"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> demographics</span>
<span id="cb4-41"></span>
<span id="cb4-42"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Demographics</span></span>
<span id="cb4-43"></span>
<span id="cb4-44"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb4-45"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_question(</span></span>
<span id="cb4-46"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  type = 'numeric',</span></span>
<span id="cb4-47"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  id = 'age',</span></span>
<span id="cb4-48"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  label = "What is your age?"</span></span>
<span id="cb4-49"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-50"></span>
<span id="cb4-51"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_question(</span></span>
<span id="cb4-52"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  type = 'mc',</span></span>
<span id="cb4-53"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  id = 'education',</span></span>
<span id="cb4-54"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  label = "What is your highest level of education?",</span></span>
<span id="cb4-55"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  option = c(</span></span>
<span id="cb4-56"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'High school' = 'hs',</span></span>
<span id="cb4-57"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Bachelor</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\'</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s degree' = 'ba',</span></span>
<span id="cb4-58"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Graduate degree' = 'grad'</span></span>
<span id="cb4-59"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  )</span></span>
<span id="cb4-60"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-61"></span>
<span id="cb4-62"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_next()</span></span>
<span id="cb4-63"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb4-64"></span>
<span id="cb4-65"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> survey_questions</span>
<span id="cb4-66"></span>
<span id="cb4-67"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Main Questions</span></span>
<span id="cb4-68"></span>
<span id="cb4-69"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb4-70"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_question(</span></span>
<span id="cb4-71"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  type = 'mc',</span></span>
<span id="cb4-72"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  id = 'satisfaction',</span></span>
<span id="cb4-73"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  label = "How satisfied are you with our product?",</span></span>
<span id="cb4-74"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  option = c(</span></span>
<span id="cb4-75"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Very satisfied' = '5',</span></span>
<span id="cb4-76"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Satisfied' = '4',</span></span>
<span id="cb4-77"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Neutral' = '3',</span></span>
<span id="cb4-78"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Dissatisfied' = '2',</span></span>
<span id="cb4-79"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    'Very dissatisfied' = '1'</span></span>
<span id="cb4-80"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  )</span></span>
<span id="cb4-81"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-82"></span>
<span id="cb4-83"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_next()</span></span>
<span id="cb4-84"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb4-85"></span>
<span id="cb4-86"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> end</span>
<span id="cb4-87"></span>
<span id="cb4-88"><span class="do" style="color: #5E5E5E;
background-color: null;
font-style: italic;">## Thank You!</span></span>
<span id="cb4-89"></span>
<span id="cb4-90">Your responses have been recorded. You may now close this window.</span>
<span id="cb4-91"></span>
<span id="cb4-92"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">{r}</span></span>
<span id="cb4-93"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd_close()</span></span>
<span id="cb4-94"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
</div>
</div>
</div>
</div>
<p>Notice how much cleaner the shorthand version is? The page boundaries are immediately visible, and there’s no visual clutter from closing tags. Your survey structure becomes easier to understand at a glance.</p>
</section><section id="backward-compatibility" class="level2"><h2 class="anchored" data-anchor-id="backward-compatibility">Backward Compatibility</h2>
<p>We want to emphasize that <strong>both syntaxes work perfectly</strong> in v0.14.0 and beyond. Your existing surveys using fence syntax will continue to work without any changes. We’re introducing shorthand syntax as the <strong>recommended</strong> approach going forward, but you’re free to use whichever style you prefer.</p>
<div class="callout callout-style-default callout-caution callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Caution
</div>
</div>
<div class="callout-body-container callout-body">
<p>Be careful not to mix both syntaxes within the same survey. Each survey must define pages using either the fence syntax or shorthand syntax exclusively.</p>
</div>
</div>
</section><section id="updated-documentation" class="level2"><h2 class="anchored" data-anchor-id="updated-documentation">Updated Documentation</h2>
<p>All of our documentation has been updated to use the new shorthand syntax as the primary example. However, we’ve kept documentation for both approaches:</p>
<ul>
<li>The <a href="https://surveydown.org/docs/page-navigation.html#defining-pages">Page Navigation</a> page explains both syntaxes in detail</li>
<li>The <a href="https://surveydown.org/docs/basic-components.html#defining-pages">Basic Components</a> page introduces shorthand syntax</li>
<li>All our <a href="https://surveydown.org/templates.html">templates</a> will be updated to use shorthand syntax</li>
</ul></section><section id="migration-guide" class="level2"><h2 class="anchored" data-anchor-id="migration-guide">Migration Guide</h2>
<p>The good news is you do not need to change anything in your existing surveys. They will continue to work as before. However, if you want to take advantage of the cleaner shorthand syntax, migrating is easy:</p>
<ol type="1">
<li>Replace <code>::: {.sd_page id=PAGE_ID}</code> with <code>--- PAGE_ID</code>
</li>
<li>Remove all closing <code>:::</code> tags</li>
<li>Make sure each page starts with <code>---</code> followed by a space and the page ID</li>
</ol>
<p>For example, convert this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>page1} </span>
<span id="cb5-2"></span>
<span id="cb5-3">Content here</span>
<span id="cb5-4"></span>
<span id="cb5-5"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span>
<span id="cb5-6"></span>
<span id="cb5-7"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:::</span> {.sd_page id<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span>page2}</span>
<span id="cb5-8"></span>
<span id="cb5-9">More content</span>
<span id="cb5-10"></span>
<span id="cb5-11"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span></code></pre></div></div>
</div>
<p>To this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> page1</span>
<span id="cb6-2"></span>
<span id="cb6-3">Content here</span>
<span id="cb6-4"></span>
<span id="cb6-5"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span> page2</span>
<span id="cb6-6"></span>
<span id="cb6-7">More content</span></code></pre></div></div>
</div>
<p>That’s all there is to it!</p>
</section><section id="looking-forward" class="level2"><h2 class="anchored" data-anchor-id="looking-forward">Looking Forward</h2>
<p>This improvement is part of our ongoing effort to make surveydown as developer-friendly as possible. We’re constantly listening to user feedback and looking for ways to reduce friction in the survey development process.</p>
<p>If you have suggestions for future improvements, please let us know through <a href="https://github.com/orgs/surveydown-dev/discussions">GitHub Discussions</a> or by filing an issue on our <a href="https://github.com/surveydown-dev/surveydown">GitHub repository</a>.</p>
</section><section id="getting-started" class="level2"><h2 class="anchored" data-anchor-id="getting-started">Getting Started</h2>
<p>To start using the shorthand syntax, simply update to surveydown v0.14.0 or later:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Install from CRAN (once 0.14.0 is released)</span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/utils/install.packages.html">install.packages</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"surveydown"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Or install the development version from GitHub</span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pak</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pak</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"surveydown-dev/surveydown"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>Then start using <code>---</code> followed by your page IDs in your survey.qmd files. It’s that simple!</p>


</section><a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>R</category>
  <category>package</category>
  <category>syntax</category>
  <category>feature</category>
  <guid>https://www.surveydown.org/blog/2025-11-15-shorthand-page-syntax/</guid>
  <pubDate>Sat, 15 Nov 2025 00:00:00 GMT</pubDate>
  <media:content url="https://www.surveydown.org/blog/2025-11-15-shorthand-page-syntax/banner.png" medium="image" type="image/png" height="96" width="144"/>
</item>
<item>
  <title>Introducing sdstudio: A companion GUI for surveydown</title>
  <dc:creator>John Paul Helveston</dc:creator>
  <dc:creator>Pingfan Hu</dc:creator>
  <link>https://www.surveydown.org/blog/2025-06-29-sdstudio/</link>
  <description><![CDATA[ 





<p>As a companion package to the <a href="https://surveydown.org/">surveydown</a> platform, <strong>sdstudio</strong> serves as a comprehensive GUI for working with surveydown surveys. It allows you to build and preview surveys as well as manage response data all without requiring programming knowledge.</p>
<p>Below is a brief walkthrough video of the <strong>sdstudio</strong> package:</p>
<div style="width:100%; text-align:center;">
<p></p><div class="quarto-video ratio ratio-16x9"><iframe data-external="1" src="https://www.youtube.com/embed/p00ivfg1B1M" title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div> <strong><em>Intro to sdstudio</em></strong><p></p>
</div>
<p><br></p>
<section id="getting-started" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="getting-started"><span class="header-section-number">1</span> Getting Started</h2>
<section id="installation" class="level3" data-number="1.1">
<h3 data-number="1.1" class="anchored" data-anchor-id="installation"><span class="header-section-number">1.1</span> Installation</h3>
<p>The <strong>sdstudio</strong> package is currently in development and can be installed directly from GitHub:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Development version</span></span>
<span id="cb1-2">pak<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pak</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"surveydown-dev/sdstudio"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ask =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span></code></pre></div></div>
<p>Since <strong>sdstudio</strong> is a companion package of <strong>surveydown</strong>, make sure to install <strong>surveydown</strong> as well:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Development version</span></span>
<span id="cb2-2">pak<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pak</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"surveydown-dev/surveydown"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ask =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># CRAN version</span></span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"surveydown"</span>)</span></code></pre></div></div>
</section>
<section id="launch" class="level3" data-number="1.2">
<h3 data-number="1.2" class="anchored" data-anchor-id="launch"><span class="header-section-number">1.2</span> Launch!</h3>
<p>Launch the studio in your browser using this function:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">sdstudio<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">launch</span>()</span></code></pre></div></div>
<p>The <strong>sdstudio</strong> interface is organized into three main tabs that follow the natural survey workflow:</p>
<ul>
<li><strong>🏗️ Build</strong>: Visual survey creation with side-by-side structure and scripts</li>
<li><strong>👁️ Preview</strong>: Real-time survey testing</li>
<li><strong>📊 Responses</strong>: Data collection, analytics, and export capabilities</li>
</ul>
</section>
</section>
<section id="the-build-tab" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="the-build-tab"><span class="header-section-number">2</span> The “Build” Tab</h2>
<section id="start-from-a-template" class="level3" data-number="2.1">
<h3 data-number="2.1" class="anchored" data-anchor-id="start-from-a-template"><span class="header-section-number">2.1</span> Start from a Template</h3>
<p>The “Build” tab is your workspace of survey construction. You can either start from a prepared template or continue with your own survey files. The “Directory” will show your current working directory, but you can change it to any directory where your survey files are stored.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>We currently have 15 templates to choose from. The <strong><em>default</em></strong> template contains a minimum basic structure for a clean start. You might also try the <strong><em>question_type</em></strong> template for a showcase of all question types, or try some advanced features with <strong><em>conditional_display</em></strong>, <strong><em>conditional_navigation</em></strong>, etc. Our <a href="https://github.com/surveydown-dev">surveydown-dev GitHub organization</a> has template repositories starting with <code>template_</code>. Feel free to search for your desired templates, clone or download the source code and try them out!</p>
</div>
</div>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/build_tab_1.png" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Start from a Template in the Build Tab</em>
</p>
</center>
<p><br></p>
</section>
<section id="build-your-survey" class="level3" data-number="2.2">
<h3 data-number="2.2" class="anchored" data-anchor-id="build-your-survey"><span class="header-section-number">2.2</span> Build Your Survey</h3>
<p>After you’ve selected your template, or if you already have an existing survey, you’ll see the dual panel of survey constructions on the “Build” tab. The “Structure” section on the left shows the page-content structure of your survey. The “Code” section on the right displays the survey scripts in a code editor.</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/build_tab_2.png" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Dual Panel of the Build Tab</em>
</p>
</center>
<p><br></p>
<section id="the-structure-section" class="level4" data-number="2.2.1">
<h4 data-number="2.2.1" class="anchored" data-anchor-id="the-structure-section"><span class="header-section-number">2.2.1</span> The Structure Section</h4>
<p>The <strong>“Structure”</strong> section on the left gives you 2 hierarchies: page and content. The pages can be toggled on to show the content, or toggled off. There are two types of content: questions and texts, with labels of “Q” and “T”, respectively.</p>
<p>There are buttons on each page and content which self-explain their capabilities. The “Add A New Page” button at the bottom allows you to create a new page.</p>
<p>The <em>question</em> content shows question ID, question type, and question label. You can review the full question details with the edit button, or view the full question definition code on the code section. The <em>text</em> content shows the first 5 words of the full piece of text.</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/build_tab_3.png" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Click on the +T/+Q button to add a text/question</em>
</p>
</center>
<p><br></p>
<p>All elements support drag-n-drop operations. After each operation, the structure will refresh and update the code editor on the right. If you move two test elements together, they will merge in to one text element.</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/build_tab_4.gif" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Dragging two texts together will merge them</em>
</p>
</center>
<p><br></p>
</section>
<section id="the-code-section" class="level4" data-number="2.2.2">
<h4 data-number="2.2.2" class="anchored" data-anchor-id="the-code-section"><span class="header-section-number">2.2.2</span> The Code Section</h4>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>For now the surveydown Studio has powerful support to <strong>survey.qmd</strong> because it is meant to be the main file for survey construction. However, even though <strong>app.R</strong> is directly editable, we still recommend that you edit it using your IDE or other text editors. All our templates have the <strong>app.R</strong> file ready to run, which can be a good starting point.</p>
</div>
</div>
<p>The <strong>“Code”</strong> section on the right is an integrated code editor that allows you to edit the survey scripts directly, with the <strong>survey.qmd</strong> file opened by default. It also reflects any operation you’ve done on the “Structure” section. The other file, <strong>app.R</strong>, is available for direct editing as well.</p>
</section>
</section>
</section>
<section id="the-preview-tab" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="the-preview-tab"><span class="header-section-number">3</span> The “Preview” Tab</h2>
<p>The “Preview” tab is where your survey comes to life. It provides a real-time, interactive preview of your survey as you build it, allowing you to see exactly how respondents will experience your survey.</p>
<section id="live-rendering" class="level3" data-number="3.1">
<h3 data-number="3.1" class="anchored" data-anchor-id="live-rendering"><span class="header-section-number">3.1</span> Live Rendering</h3>
<p>Every time you make changes in the Build tab, the survey is live-rendered and revealed in the Preview tab. It takes a couple of seconds to render, so if you switch to the Preview tab too early, you’ll see message of survey being rendered. After rendering is done, the survey will be available.</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/preview_tab_1.gif" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>The survey preview is live and interactive</em>
</p>
</center>
<p><br></p>
</section>
<section id="desktop-and-mobile-views" class="level3" data-number="3.2">
<h3 data-number="3.2" class="anchored" data-anchor-id="desktop-and-mobile-views"><span class="header-section-number">3.2</span> Desktop and Mobile Views</h3>
<p>You can toggle between “Desktop View” and “Mobile View” using the pair of buttons at the top right corner:</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/preview_tab_2.gif" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Toggling between desktop and mobile views</em>
</p>
</center>
<p><br></p>
</section>
<section id="new-sessions" class="level3" data-number="3.3">
<h3 data-number="3.3" class="anchored" data-anchor-id="new-sessions"><span class="header-section-number">3.3</span> New Sessions</h3>
<p>You might have noticed there is a green refresh button on the top right as well. This is for you to manually refresh the preview if you want to restart a session:</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/preview_tab_3.gif" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Restart a new session using the refresh button</em>
</p>
</center>
<p><br></p>
</section>
</section>
<section id="the-responses-tab" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="the-responses-tab"><span class="header-section-number">4</span> The “Responses” Tab</h2>
<p>We built <strong>sdstudio</strong> for two purposes: for designing surveys and for managing survey response data. You can use the studio for either or both purposes.</p>
<p>The “Responses” tab is used to view two forms of survey response data:</p>
<ol type="1">
<li><strong>Local Mode</strong>: This mode allows you to view “preview data” while locally previewing your survey without having a database connection. The preview data are stored in a local “preview_data.csv” file and are purely available for the purposes of previewing what your data will look like once you have a database connection.</li>
<li><strong>DB Mode</strong>: After creating and testing your survey, you can add a database connection to start collecting survey responses in your live database.</li>
</ol>
<p>Lets go through each of these use cases in details.</p>
<section id="local-mode" class="level3" data-number="4.1">
<h3 data-number="4.1" class="anchored" data-anchor-id="local-mode"><span class="header-section-number">4.1</span> Local Mode</h3>
<p>All our templates have <strong>Local Mode</strong> enabled by default, because we recommend you to start from local testing. To start with your local testing, you can simply go through all 3 tabs in order: <strong>Build</strong>, <strong>Preview</strong>, and then <strong>Responses</strong>.</p>
<p>Below is a brief walkthrough of the process:</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/responses_tab_1.gif" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Build, Preview, and Responses in Sequence</em>
</p>
</center>
<p><br></p>
</section>
<section id="db-mode" class="level3" data-number="4.2">
<h3 data-number="4.2" class="anchored" data-anchor-id="db-mode"><span class="header-section-number">4.2</span> DB Mode</h3>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>For instructions on how to obtain your database credentials, see the <a href="https://surveydown.org/docs/storing-data.html#getting-your-supabase-credentials">Storing Data</a> documentation page.</p>
</div>
</div>
<p>To get started with viewing your database response data, you need to firstly switch to <strong>DB Mode</strong> by clicking the “DB Mode” button on the top right corner. This is available in all 3 tabs. Then, in your “Responses” tab, you’ll see a “Database Connection” section on the top. Toggle on the “Settings” button and fill in your database credentials. You can test the connection by clicking the “Test Connection” button. If you have already set up your database credentials using <code>sd_db_config()</code> to create a local <code>.env</code>, then your credentials should show here.</p>
<p>In order to have a clean start, we recommend you to name a new table in the “Table” field of “Database Connection”. Upon clicking “Test Connection”, this table will only be a placeholder, and the database will create such table once you start your first survey run.</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/responses_tab_2.png" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Input your credentials and create a new table</em>
</p>
</center>
<p><br></p>
<p>If the connection is successful, you will see a “Connected” status message in green. The “Choose a table to view” section will show the new table you just created, but all fields will be empty. They will be filled in once you run your survey in the <strong>Preview</strong> tab.</p>
<p>After you’ve taken care of the database connection, you can go back to the <strong>Build</strong> tab and proceed with your survey construction, following the exact same steps. The only difference is that now, when you run the survey in the <strong>Preview</strong> tab, your responses will be stored in the database table you just created instead of the local “preview_data.csv” file.</p>
</section>
<section id="viewing-other-tables" class="level3" data-number="4.3">
<h3 data-number="4.3" class="anchored" data-anchor-id="viewing-other-tables"><span class="header-section-number">4.3</span> Viewing other tables</h3>
<p>It is important to note that you can use the “Responses” tab to view all tables stored in your database. For example, if you have multiple surveys you are working on (each in a separate folder) that share the same database, you can select other tables to view from the “Responses” tab.</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/responses_tab_3.png" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Input your database credentials</em>
</p>
</center>
<p><br></p>
<p>If the connection is successful, you will see a “Connected” status message in green. You can choose your desired response table from the dropdown menu, review its progress and details, and download the csv file if needed:</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-06-29-sdstudio/images/responses_tab_4.gif" style="width: 100%; max-width: 1000px; border: 1px solid #ddd;">
<p style="color: gray; font-weight: bold;">
<em>Fill in your database credentials and click on the “Test Connection” button</em>
</p>
</center>
<p><br></p>
</section>
</section>
<section id="data-security" class="level2" data-number="5">
<h2 data-number="5" class="anchored" data-anchor-id="data-security"><span class="header-section-number">5</span> Data Security</h2>
<section id="the-.env-file" class="level3" data-number="5.1">
<h3 data-number="5.1" class="anchored" data-anchor-id="the-.env-file"><span class="header-section-number">5.1</span> The <code>.env</code> File</h3>
<p>When you input your database credentials in the “Responses” tab, it creates a local <code>.env</code> file in your current working directory, which is a hidden file. This file is used to store environment variables securely. Along with this file, there will be a <code>.gitignore</code> file created with <code>.env</code> added to prevent it from being accidentally pushed to your git repository. This is a good practice to keep your credentials safe.</p>
<p>In this <code>.env</code> file, you will find the following variables:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Database connection settings for surveydown</span></span>
<span id="cb4-2">SD_HOST<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"your-database-host"</span></span>
<span id="cb4-3">SD_PORT<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"your-database-port"</span></span>
<span id="cb4-4">SD_DBNAME<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"your-database-name"</span></span>
<span id="cb4-5">SD_USER<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"your-database-username"</span></span>
<span id="cb4-6">SD_PASSWORD<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"your-database-password"</span></span>
<span id="cb4-7">SD_TABLE<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"your-database-table"</span></span></code></pre></div></div>
<p>The editing of this file is bi-directional, so you can either edit on this file, or use the <strong>sdstudio</strong> interface.</p>
</section>
<section id="gssapi-encryption" class="level3" data-number="5.2">
<h3 data-number="5.2" class="anchored" data-anchor-id="gssapi-encryption"><span class="header-section-number">5.2</span> GSSAPI Encryption</h3>
<p>The <code>sdstudio::launch()</code> function allows the <code>gssencmode</code> argument. It controls the encryption mode for database connections. This is crucial for ensuring secure communication with your database, especially when handling sensitive survey data.</p>
<p>By default, we set <code>gssencmode = "auto"</code>, which attempts to use GSSAPI encryption if available, falling back to a plain connection if not. This is the recommended mode for most users. The connection status will show a green “Connected (GSSAPI enabled)” message if GSSAPI is successfully enabled, or a yellow “Connected (GSSAPI disabled)” message if it falls back to plain connection:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Auto mode (recommended) - tries GSSAPI first, falls back if needed</span></span>
<span id="cb5-2">sdstudio<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">launch</span>()</span></code></pre></div></div>
<p>However, if you want to explicitly control the encryption mode, you can set <code>gssencmode</code> to one of the following values:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Prefer mode - only use GSSAPI</span></span>
<span id="cb6-2">sdstudio<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">launch</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">gssencmode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"prefer"</span>)</span>
<span id="cb6-3"></span>
<span id="cb6-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Disable mode - forces plain connection (useful for VPN environments)</span></span>
<span id="cb6-5">sdstudio<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">launch</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">gssencmode =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"disable"</span>)</span></code></pre></div></div>
</section>
</section>
<section id="conclusion" class="level2" data-number="6">
<h2 data-number="6" class="anchored" data-anchor-id="conclusion"><span class="header-section-number">6</span> Conclusion</h2>
<p>As a companion GUI for the <strong>surveydown</strong> platform, <strong>sdstudio</strong> significantly simplifies the survey creation process. It allows users to build, preview, and manage surveys through an intuitive interface, without requiring extensive programming skills. The three-tab workflow - Build, Preview, and Responses - provides a comprehensive solution that covers the entire survey lifecycle.</p>
<p>If you have any questions or feedback you’d like to share, please drop us a line using <a href="https://github.com/orgs/surveydown-dev/discussions">GitHub Discussions</a>.</p>
<hr>
<p><em>For more information, visit the <a href="https://sdstudio.surveydown.org">sdstudio documentation</a> or explore the <a href="https://surveydown.org">surveydown platform</a>.</em></p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>R</category>
  <category>package</category>
  <category>shiny</category>
  <category>tutorial</category>
  <category>GUI</category>
  <guid>https://www.surveydown.org/blog/2025-06-29-sdstudio/</guid>
  <pubDate>Sun, 29 Jun 2025 00:00:00 GMT</pubDate>
  <media:content url="https://www.surveydown.org/blog/2025-06-29-sdstudio/banner.png" medium="image" type="image/png" height="96" width="144"/>
</item>
<item>
  <title>surveydown Gadgets for Page and Question Creation</title>
  <dc:creator>John Paul Helveston</dc:creator>
  <dc:creator>[Pingfan Hu](https://pingfanhu.com)</dc:creator>
  <link>https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/</link>
  <description><![CDATA[ 





<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>As of version 0.10.0, surveydown now has shiny gadgets to make it easier to insert pages and questions into your survey.qmd file. This post highlights how to use them in your survey building workflow.</p>
<p>To view a full-course survey building workflow, proceed to the <a href="../../docs/basic-components.html">Basic Components</a> page.</p>
</div>
</div>
<section id="introduction" class="level2" data-number="1">
<h2 data-number="1" class="anchored" data-anchor-id="introduction"><span class="header-section-number">1</span> Introduction</h2>
<p>While surveydown works with various IDEs, the gadget features perform best in RStudio. These gadgets provide a user-friendly interface for creating survey elements without having to remember the exact syntax or function parameters.</p>
<p>Two primary gadgets are offered by surveydown:</p>
<ol type="1">
<li><strong>Survey Page Gadget</strong> - Creates a new survey page</li>
<li><strong>Survey Question Gadget</strong> - Creates a new survey question</li>
</ol>
<p>Here is a showcase of the <strong>Survey Page Gadget</strong> in RStudio:</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/images/gadget_of_page.gif" style="width: 100%; max-width: 1000px;">
</center>
<p><br></p>
<p>The <strong>Survey Question Gadget</strong>:</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/images/gadget_of_question.gif" style="width: 100%; max-width: 1000px;">
</center>
<p><br></p>
<p>As you can see, these gadgets simplify the process of adding survey components. This blog walks you through how to access and use these gadgets.</p>
</section>
<section id="accessing-the-gadgets" class="level2" data-number="2">
<h2 data-number="2" class="anchored" data-anchor-id="accessing-the-gadgets"><span class="header-section-number">2</span> Accessing the Gadgets</h2>
<p>The gadgets are powered by the <code>sd_page_gadget()</code> and <code>sd_question_gadget()</code> functions, but you don’t need to call these functions directly.</p>
<p>You can access these gadgets in RStudio in two ways:</p>
<section id="using-the-addins-menu" class="level3" data-number="2.1">
<h3 data-number="2.1" class="anchored" data-anchor-id="using-the-addins-menu"><span class="header-section-number">2.1</span> Using the Addins Menu</h3>
<ol type="1">
<li>Click on the “Addins” dropdown menu in the RStudio toolbar</li>
<li>Type “surveydown” in the search box</li>
<li>Select either “Add Survey Page” or “Add Survey Question”</li>
</ol>
<p>Below is a screenshot of the Addins menu with surveydown gadgets:</p>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/images/addins_menu.png" style="width: 100%; max-width: 400px;">
</center>
<p><br></p>
</section>
<section id="keyboard-shortcuts-recommended" class="level3" data-number="2.2">
<h3 data-number="2.2" class="anchored" data-anchor-id="keyboard-shortcuts-recommended"><span class="header-section-number">2.2</span> Keyboard Shortcuts (Recommended)</h3>
<p>For more efficient workflow, set up keyboard shortcuts:</p>
<ol type="1">
<li>Go to Tools → Addins → Browse Addins…</li>
</ol>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/images/shortcut_1.png" style="width: 100%; max-width: 400px;">
</center>
<p><br></p>
<ol start="2" type="1">
<li>In the Addins popup window, click on the “Keyboard shortcuts…” button on the bottom left corner.</li>
</ol>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/images/shortcut_2.png" style="width: 100%; max-width: 600px;">
</center>
<p><br></p>
<ol start="3" type="1">
<li>Input “survey” in the search box.</li>
</ol>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/images/shortcut_3.png" style="width: 100%; max-width: 600px;">
</center>
<p><br></p>
<ol start="4" type="1">
<li>Assign the following shortcuts:
<ul>
<li><code>Ctrl+Shift+P</code> for the Survey Page Gadget</li>
<li><code>Ctrl+Shift+Q</code> for the Survey Question Gadget</li>
</ul>
Or if you have other preferences, feel free to customize them.</li>
</ol>
</section>
</section>
<section id="using-the-gadgets" class="level2" data-number="3">
<h2 data-number="3" class="anchored" data-anchor-id="using-the-gadgets"><span class="header-section-number">3</span> Using the Gadgets</h2>
<section id="survey-page-gadget" class="level3" data-number="3.1">
<h3 data-number="3.1" class="anchored" data-anchor-id="survey-page-gadget"><span class="header-section-number">3.1</span> Survey Page Gadget</h3>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/images/gadget_of_page.png" style="width: 100%; max-width: 400px;">
</center>
<p><br></p>
<p>The page gadget is straightforward:</p>
<ol type="1">
<li>Press <code>Ctrl+Shift+P</code> (or use the Addins menu)</li>
<li>Enter a Page ID (no spaces allowed)</li>
<li>Click “Create Page” or press Enter</li>
</ol>
<p>This will insert a properly formatted page block at your cursor position, including an R code chunk ready for adding questions.</p>
</section>
<section id="survey-question-gadget" class="level3" data-number="3.2">
<h3 data-number="3.2" class="anchored" data-anchor-id="survey-question-gadget"><span class="header-section-number">3.2</span> Survey Question Gadget</h3>
<br>
<center>
<img src="https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/images/gadget_of_question.png" style="width: 100%; max-width: 400px;">
</center>
<p><br></p>
<p>The question gadget offers more options:</p>
<ol type="1">
<li>Press <code>Ctrl+Shift+Q</code> (or use the Addins menu)</li>
<li>Fill in the following:
<ul>
<li><strong>Question Type</strong>: Select from the dropdown (default is “Multiple Choice”)</li>
<li><strong>Question ID</strong>: Enter a unique identifier (no spaces)</li>
<li><strong>Question Label</strong>: Enter the actual question text</li>
</ul></li>
<li><strong>R Chunk Option</strong>: Check this box if you need the question to be inserted within an R code chunk</li>
<li>Click “Create Question” or press Enter</li>
</ol>
<p>Note that if you created the question inside an existing page’s R chunk, you don’t need to check the “R Chunk Option”. If you’re adding a question elsewhere and need it to be in an R chunk, check that box.</p>
</section>
</section>
<section id="example-workflow" class="level2" data-number="4">
<h2 data-number="4" class="anchored" data-anchor-id="example-workflow"><span class="header-section-number">4</span> Example Workflow</h2>
<p>Here’s how a typical workflow might look:</p>
<ol type="1">
<li>Create a new page:
<ul>
<li>Press <code>Ctrl+Shift+P</code></li>
<li>Key in your Page ID</li>
<li>Press Enter</li>
</ul></li>
<li>Add a question:
<ul>
<li>Press <code>Ctrl+Shift+Q</code></li>
<li>Select your desired question type</li>
<li>Key in your Question ID</li>
<li>Key in your Question Label</li>
<li>Press Enter</li>
<li>Modify your Question Options as needed</li>
</ul></li>
<li>Add more questions as needed by repeating step 2.</li>
</ol>
<p>By following these steps and using the gadgets, you’ll create well-structured surveys much faster than coding everything manually.</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>RStudio</category>
  <category>tutorial</category>
  <guid>https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/</guid>
  <pubDate>Tue, 08 Apr 2025 00:00:00 GMT</pubDate>
  <media:content url="https://www.surveydown.org/blog/2025-04-08-surveydown-gadgets/banner.png" medium="image" type="image/png" height="96" width="144"/>
</item>
<item>
  <title>surveydown is on CRAN 🎉!</title>
  <dc:creator>John Paul Helveston</dc:creator>
  <link>https://www.surveydown.org/blog/2024-12-20-surveydown-on-cran/</link>
  <description><![CDATA[ <p>We have some exciting news to share - surveydown is on CRAN 🎉!</p>
<p>You can now install surveydown from CRAN using the usual <code><a href="https://rdrr.io/r/utils/install.packages.html">install.packages()</a></code> function:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/utils/install.packages.html">install.packages</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"surveydown"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>Actually, surveydown has been on CRAN since v0.4.0, but we’ve been making so many updates that we’re now already on v0.7.2 before we could even make a post about being on CRAN!</p>
<p>So it seems about time we highlight some of the improvements and new features we’ve added recently.</p>
<section id="new-functions-features" class="level2"><h2 class="anchored" data-anchor-id="new-functions-features">New functions / features</h2>
<p>We added a whole bunch of new functions and features since v0.3.0, which was a major architectural change to the package. But the changes we made in v0.3.0 made it lot easier to support more features. There have been a lot, so I’m probably missing some, but here are some quick highlights that are worth calling out:</p>
<ul>
<li>In <code>sd_question()</code>, we added a new <code>type = "matrix"</code> to support matrix type questions.</li>
<li>We added a new <code>sd_is_answered()</code> function to check if a question is answered or not. This is useful for conditional reactive questions defined in the server.</li>
<li>We added a new <code>sd_completion_code()</code> function that generates a random completion code for your survey.</li>
<li>We added a new <code>sd_close()</code> function to make a button that closes the survey.</li>
<li>
<a href="https://github.com/StefanMunnes">Stefan Munnes</a> <a href="https://github.com/surveydown-dev/surveydown/pull/138">added</a> a translation feature that allows you to customize the system messages in the app to any language you want.</li>
<li>We modified how data handling is done so that each respondent’s state in the survey can be restored via cookies if they refresh the browser window or close and re-open the window. Before, respondents would be sent back to the start of the survey and a new entry in the database would be created, so this features allows respondents to pause and come back to the survey without that happening.</li>
<li>We added two new helper functions, <code>sd_add_question()</code> and <code>sd_add_page()</code>, that make it easier to quickly create template questions and pages. They work like this:</li>
</ul>
<center>
<img src="https://www.surveydown.org/blog/2024-12-20-surveydown-on-cran/sd_add.gif" width="700">
</center>
</section><section id="performance-improvements" class="level2"><h2 class="anchored" data-anchor-id="performance-improvements">Performance improvements</h2>
<p>One major improvement we’ve made is to streamline how the <code>survey.qmd</code> file is updating. Before you needed to render the <code>survey.qmd</code> file yourself before running the <code>app.R</code> file, but now you actually never need to render it. All rendering is handled when you run the shiny app via the <code>app.R</code> file.</p>
<p>And this rendering is “smart” too - it renders the <code>survey.qmd</code> file into an html file, then it parses that file for all of the content needed for the survey and stores each piece in a <code>_survey</code> folder. This folder is then what the shiny app uses to load the survey. If no changes are detected in the <code>survey.qmd</code> file or any of the components in the <code>_survey</code> folder, then the app will always load content from the pre-rendered content in the <code>_survey</code> folder, which will load nearly instantaneously! Only if you make a change to your survey will it be re-rendered, and again once that rendering is done once it won’t run again until another change is detected. This results in a much more efficient app that loads nearly instantaneously.</p>
<p>We also improved the database updating to be much more efficient. It used to run a write operation to the database on every single question ineraction, but that slowed down the app significantly. Now that we have cookies enabled, we do the immediate record keeping in the cookies and only write to the database when the respondent closes the survey or turns the page. This is a more reasonable compromise that makes the app feel snappy while still ensuring that the data is saved even if the respondent accidentally closes the window.</p>
</section><section id="our-first-community-contributions" class="level2"><h2 class="anchored" data-anchor-id="our-first-community-contributions">Our first community contributions!</h2>
<p>Over the past few months, we’ve been getting a lot of contributions from the community! We’ve been able to merge a few pull requests that add some new features and fix some bugs. Here are some of the highlights:</p>
<ul>
<li>
<a href="https://github.com/StefanMunnes">Stefan Munnes</a> added a new translation feature that allows you to customize the system messages in the app to any language you want. He also helped us update <code>sd_output()</code> to be able to output the chosen question values, chosen question option label(s), and the question label itself. This addresses <a href="https://github.com/orgs/surveydown-dev/discussions/128">feature request #128</a>.</li>
<li>
<a href="https://github.com/zainhoda1">Zain Hoda</a> contributed a new <code>auto_scroll</code> parameter to the <code>sd_server()</code> function that allows you to turn off auto scrolling. This is useful if you have a lot of questions and want to make sure the respondent can see the entire question.</li>
</ul>
<p>We’re excited to see what the community will build with surveydown! If you build something with surveydown, please let us know on the <a href="https://github.com/orgs/surveydown-dev/discussions">GitHub Discussions</a> so we can highlight your work!</p>


</section><a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>R</category>
  <category>CRAN</category>
  <guid>https://www.surveydown.org/blog/2024-12-20-surveydown-on-cran/</guid>
  <pubDate>Fri, 20 Dec 2024 00:00:00 GMT</pubDate>
  <media:content url="https://www.surveydown.org/blog/2024-12-20-surveydown-on-cran/banner.png" medium="image" type="image/png" height="96" width="144"/>
</item>
<item>
  <title>New architecture in v0.3.0 (and loads of breaking changes)!</title>
  <dc:creator>John Paul Helveston</dc:creator>
  <link>https://www.surveydown.org/blog/2024-09-18-new-app-design/</link>
  <description><![CDATA[ <p>The surveydown package is only a couple months old, and thanks to many early users we learned about some design flaws that needed to be fixed. As a result, with the release of {surveydown} 0.3.0, the package has undergone a major overhaul to improve security, modularity, and extensibility.</p>
<p>We introduced several major breaking changes in this release, so we felt we should make a blog post to both explain why we felt these changes were needed as well as introduce the new architecture we have adopted.</p>
<section id="motivation" class="level2"><h2 class="anchored" data-anchor-id="motivation">Motivation</h2>
<p>In the original conception of surveydown, the entire survey was defined in a single Quarto shiny document that would render into a shiny app. While this was a rather parsimonious design, it also had some flaws that weren’t immediately apparent.</p>
<p>Perhaps the largest issue was <strong>page security</strong> (see <a href="https://github.com/surveydown-dev/surveydown/issues/93">this issue</a>). With Quarto shiny documents, the qmd file is first rendered into a static html page that is then used to define the elements of the user interface in the resulting shiny app. This meant that for us to introduce <em>pages</em>, we relied on a combination of JS and CSS to hide and show the page divs based on users clicking on next buttons. While this resulted in a nice user experience, under the hood the entire app was still just one big html page with all of the content available.</p>
<p>This design meant that anyone could still see the source code to any component of the survey they wanted. A user could simply right-click and open “Inspect” then manually change the CSS of a page div from <code>style="display: none;"</code> to <code>style="display: show;"</code> and boom - the “page” would appear!</p>
<p>This was obviously a major security issue as pages with things like completion codes or redirect buttons at the end could be easily shown without going through the whole survey. The only solution was an architectural overhaul that would only show the content on one page at a time.</p>
</section><section id="new-architecture" class="level2"><h2 class="anchored" data-anchor-id="new-architecture">New architecture</h2>
<p>The new architecture employs a two-file design composed of a <em>survey</em> and an <em>app</em> that renders to a traditional Shiny app:</p>
<ul>
<li>
<code>survey.qmd</code>: A Quarto document that contains the survey content (pages, questions, etc), which renders to an HTML file.</li>
<li>
<code>app.R</code>: An R script defining a Shiny app that contains the global settings (libraries, database configuration, etc.) and server configuration options (e.g., conditional skipping / display, etc.).</li>
</ul>
<p><strong>These files must be named <code>survey.qmd</code> and <code>app.R</code></strong>.</p>
<p>They typically look something like this:</p>
<div class="tabset-margin-container"></div><div class="panel-tabset">
<ul class="nav nav-tabs">
<li class="nav-item"><a class="nav-link active" id="tabset-1-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-1" aria-controls="tabset-1-1" aria-selected="true" href=""><code>survey.qmd</code> file</a></li>
<li class="nav-item"><a class="nav-link" id="tabset-1-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-2" aria-controls="tabset-1-2" aria-selected="false" href=""><code>app.R</code> file</a></li>
</ul>
<div class="tab-content">
<div id="tabset-1-1" class="tab-pane active" aria-labelledby="tabset-1-1-tab">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb1-2"><span class="an" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">format:</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> html</span></span>
<span id="cb1-3"><span class="an" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">echo:</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> false</span></span>
<span id="cb1-4"><span class="an" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">warning:</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> false</span></span>
<span id="cb1-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb1-6"></span>
<span id="cb1-7"></span>
<span id="cb1-8">::: {.cell}</span>
<span id="cb1-9"></span>
<span id="cb1-10"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{.r .cell-code}</span></span>
<span id="cb1-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(surveydown)</span>
<span id="cb1-12"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb1-13">:::</span>
<span id="cb1-14"></span>
<span id="cb1-15"></span>
<span id="cb1-16">::: {#welcome .sd-page}</span>
<span id="cb1-17"></span>
<span id="cb1-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"># Welcome to our survey!</span></span>
<span id="cb1-19"></span>
<span id="cb1-20"></span>
<span id="cb1-21">::: {.cell}</span>
<span id="cb1-22"></span>
<span id="cb1-23"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{.r .cell-code}</span></span>
<span id="cb1-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span>(</span>
<span id="cb1-25">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type  =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mc'</span>,</span>
<span id="cb1-26">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id    =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'penguins'</span>,</span>
<span id="cb1-27">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Which type of penguin do you like the best?"</span>,</span>
<span id="cb1-28">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb1-29">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Adélie'</span>    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'adelie'</span>,</span>
<span id="cb1-30">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Chinstrap'</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'chinstrap'</span>,</span>
<span id="cb1-31">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Gentoo'</span>    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'gentoo'</span></span>
<span id="cb1-32">  )</span>
<span id="cb1-33">)</span>
<span id="cb1-34"></span>
<span id="cb1-35"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_next</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">next_page =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'end'</span>)</span>
<span id="cb1-36"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb1-37">:::</span>
<span id="cb1-38"></span>
<span id="cb1-39"></span>
<span id="cb1-40">:::</span>
<span id="cb1-41"></span>
<span id="cb1-42">::: {#end .sd-page}</span>
<span id="cb1-43"></span>
<span id="cb1-44">This it the last page in the survey</span>
<span id="cb1-45"></span>
<span id="cb1-46">:::</span></code></pre></div></div>
</div>
<div id="tabset-1-2" class="tab-pane" aria-labelledby="tabset-1-2-tab">
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;"><a href="https://rdrr.io/r/base/library.html">library</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org">surveydown</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">db</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_database.html">sd_database</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  host   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>,</span>
<span>  dbname <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>,</span>
<span>  port   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>,</span>
<span>  user   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>,</span>
<span>  table  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>,</span>
<span>  ignore <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">server</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">input</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">output</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">session</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span></span>
<span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define conditional skip logic here (skip to page if a condition is true)</span></span>
<span>  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_skip_if.html">sd_skip_if</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define  conditional display logic here (show a question if a condition is true)</span></span>
<span>  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_show_if.html">sd_show_if</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Main server to control the app</span></span>
<span>  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_server.html">sd_server</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">shiny</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/pkg/shiny/man/shinyApp.html">shinyApp</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ui <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_ui.html">sd_ui</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span>, server <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">server</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
</div>
</div>
</div>
<p>This approach allows us to separate the <em>survey content</em> (in the <code>survey.qmd</code> file) from the <em>survey logic</em> (in the <code>app.R</code> file), which comes with a few benefits:</p>
<ol type="1">
<li>
<strong>Security</strong>: Since the rendered survey content is no longer directly embedded in the app as a single html page, it makes it much harder for users to tamper with the content. Only the content on one page at a time will be rendered by the server.</li>
<li>
<strong>Clarity</strong>: With two files, it is now clearer where the survey content versus control logic should be defined. Before, all of the server logic was in a single server code chunk at the end of the <code>survey.qmd</code> file, which required the user to scroll up and down to edit the server logic versus the survey content. Now a user can have both files open in two tabs in an IDE and more easily edit the survey content and server content.</li>
<li>
<strong>Simplicity</strong>: The new design eliminates the need for a Quarto extension to render the survey. This allows us to ship all of the core functionality of surveydown as a single R package, which is installed globally on your system.</li>
</ol>
<p>The updated documentation of the <a href="https://surveydown.org/docs/basic-components">Basic Components</a> page reflects this new design.</p>
</section><section id="new-page-architecture" class="level2"><h2 class="anchored" data-anchor-id="new-page-architecture">New page architecture</h2>
<p>The motivation to secure the page content led to a totally new approach to designing the survey pages. Our new approach actually renders the <code>survey.qmd</code> into a static html page and then parses it into a list of page objects. Each page object is itself a list of elements, including the page ID, question IDs, etc., as well as the rendered html content for that page.</p>
<p>The <code><a href="https://pkg.surveydown.org/reference/sd_server.html">sd_server()</a></code> function then uses this list of page objects to display one page at a time via a <code><a href="https://rdrr.io/pkg/shiny/man/renderUI.html">shiny::renderUI()</a></code> function into a single “main” output. This approach allowed us to control what content is being served, eliminating the ability of survey respondents to see anything other than the content on the current page.</p>
<p>This approach also gave us the opportunity to overhaul how pagination works in general. Previously, users had to add a <code>sd_next(next_page = "page_id")</code> button at the end of each page, making sure to specify the next page to go to. This was a bit annoying as most of the time you just want to go to the next page, so specifying it felt redundant. Now users can simply add <code><a href="https://pkg.surveydown.org/reference/sd_next.html">sd_next()</a></code> at the bottom of each page and the server will go to the next page by default. If you want to direct the respondent to a different page, then you specify the target page using <code>sd_next(next_page = "page_id")</code>.</p>
</section><section id="improved-conditional-show-and-skip-logic" class="level2"><h2 class="anchored" data-anchor-id="improved-conditional-show-and-skip-logic">Improved conditional show and skip logic</h2>
<p>Conditionally displaying questions or skipping to pages is a core logic that many surveys need. Our original approach was relatively clunky, so since we were already introducing many breaking designs, we figured we should overhaul the logic for conditional skipping and displaying.</p>
<p>The new approach uses just two functions: <code><a href="https://pkg.surveydown.org/reference/sd_skip_if.html">sd_skip_if()</a></code> and <code><a href="https://pkg.surveydown.org/reference/sd_show_if.html">sd_show_if()</a></code>. These functions can be provided in the main <code>server()</code> function in the <code>app.R</code> file to define the conditions and targets for either conditional displaying a question or conditionally skipping to a page. The structure for each condition in these new functions is always as follows:</p>
<blockquote class="blockquote">
<p><code>&lt;condition&gt; ~ "target_question_id"</code></p>
</blockquote>
<p>As an example, let’s say we want to show a question called <code>"penguins_other"</code> if the respondent chose the <code>"other"</code> option in a question called <code>"penguins"</code>. We could do this with the following code in the <code>app.R</code> file:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">server</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">input</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">output</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">session</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span></span>
<span>  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_show_if.html">sd_show_if</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">input</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">penguins</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"other"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"penguins_other"</span></span>
<span>  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span>  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_server.html">sd_server</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>db <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">db</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</div>
<p>You can provide multiple conditions to the <code><a href="https://pkg.surveydown.org/reference/sd_show_if.html">sd_show_if()</a></code> function, each separated by a comma. The <code><a href="https://pkg.surveydown.org/reference/sd_skip_if.html">sd_skip_if()</a></code> function works the same way, but it will skip to a target page instead of showing a target question. There is also an <code><a href="https://pkg.surveydown.org/reference/sd_stop_if.html">sd_stop_if()</a></code> to stop the navigation under centain conditions. See the revised <a href="https://surveydown.org/docs/conditional-logic">Conditional Logic</a> page for more details on the new changes.</p>
</section><section id="no-more-sd_config-function" class="level2"><h2 class="anchored" data-anchor-id="no-more-sd_config-function">No more <code>sd_config()</code> function</h2>
<p>One more small change we made is that the <code>sd_config()</code> function is no longer needed. Since we moved the conditional skip and show logic into their own functions, we took the remaining arguments that used to be provided to <code>sd_config()</code> and added them to the <code><a href="https://pkg.surveydown.org/reference/sd_server.html">sd_server()</a></code> function as options. You can now simply pass these arguments to the <code><a href="https://pkg.surveydown.org/reference/sd_server.html">sd_server()</a></code> function in the <code>app.R</code> file.</p>
</section><section id="our-apologies" class="level2"><h2 class="anchored" data-anchor-id="our-apologies">Our apologies</h2>
<p>That’s about it for the changes with v0.3.0. We want to send our deepest apologies for anyone who has already begun a study using the orginal design. The most recent version prior to v0.3.0 was v0.2.4, so this is the version you should install if you want to stick with the old design.</p>
<p>That said, all development will now continue on this new design, so we strongly recommend updating to the new version and converting any existing surveys to the new design. The biggest change you’ll need to make is to move your server logic out of the <code>survey.qmd</code> file and into the <code>app.R</code> file. We’ve also updated all our <a href="https://surveydown.org/templates">templates</a> to the new design, so you can refer to these for examples on how to convert your existing surveys.</p>


</section><a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>R</category>
  <guid>https://www.surveydown.org/blog/2024-09-18-new-app-design/</guid>
  <pubDate>Wed, 18 Sep 2024 00:00:00 GMT</pubDate>
  <media:content url="https://www.surveydown.org/blog/2024-09-18-new-app-design/banner.png" medium="image" type="image/png" height="96" width="144"/>
</item>
<item>
  <title>Choice-based conjoint surveys in R with surveydown</title>
  <dc:creator>John Paul Helveston</dc:creator>
  <link>https://www.surveydown.org/blog/2024-08-28-choice-based-conjoint-surveys-with-surveydown/</link>
  <description><![CDATA[ <div class="callout callout-style-default callout-important callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>This post was updated on 2025-09-14 to match the latest package version</strong></p>
</div>
</div>
<p>Because <a href="https://surveydown.org/">surveydown</a> surveys run as a shiny app, you can include custom logic in the background by writing some <i class="fa-brands fa-r-project" aria-label="r-project"></i> code in your server. In this post, I’m going to show you one approach for using surveydown to create a particular type of complex survey: a <strong>choice-based conjoint survey</strong>.</p>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>If you’re unfamiliar with what a conjoint survey is, take a look at this <a href="https://sawtoothsoftware.com/conjoint-analysis/cbc">quick introduction</a>.</p>
</div>
</div>
<p>The key component of a choice-based conjoint survey is asking repsondents to make choices from randomized sets of choice questions. So the hard part is figuring out a way to show each respondent a different set of randomized questions. This post shows how you can achieve this in surveydown.</p>
<p>Throughout this post, I will use a demo survey about people’s preferences for apples with three attributes: <code>type</code>, <code>price</code>, and <code>freshness</code>.<sup>1</sup> I will focus on one structure for the conjoint survey that uses the <a href="https://surveydown.org/docs/question-types.html#mc_buttons"><code>mc_buttons</code></a> question type for the main choice questions. You can view a live demo of that survey and the template used to create it <a href="https://surveydown.org/templates/conjoint_buttons.html">here</a>. An alternative structure is to display choice options in a table - that template can be found <a href="https://surveydown.org/templates/conjoint_tables">here</a>.</p>
<section id="introduction" class="level2"><h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>If you’ve never used surveydown before, take a look at the <a href="https://surveydown.org/docs/getting-started.html">Getting Started</a> page to get a quick introduction to the package and how to use it to make a survey.</p>
<p>The basic concept is this:</p>
<ol type="1">
<li>Design your survey as a <a href="https://quarto.org/">Quarto</a> document using markdown and R code.</li>
<li>Convert your survey into a <a href="https://shiny.posit.co/">Shiny</a> app that can be hosted online and sent to respondents.</li>
<li>Store your survey responses in a <a href="https://supabase.com/">Supabase</a> database.</li>
</ol></section><section id="getting-started" class="level2"><h2 class="anchored" data-anchor-id="getting-started">Getting started</h2>
<p>For this post, we recommend starting from the demo survey available <a href="https://surveydown.org/templates/conjoint_buttons.html">here</a>. It provides an already working survey that you can modify to the needs of your conjoint survey.</p>
<p>The demo repo has a lot of files in it, but the main files defining the survey itself are:</p>
<ul>
<li>
<code>survey.qmd</code>: The main body of the survey.</li>
<li>
<code>app.R</code>: The app file containing the server logic implemented in the survey, including randomizing questions, connecting to a database, etc.</li>
</ul>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>We recommend opening the <code>survey.Rproj</code> if you’re working in RStudio to make sure RStudio opens to the correct project folder.</p>
</div>
</div>
</section><section id="content-in-the-survey-body" class="level2"><h2 class="anchored" data-anchor-id="content-in-the-survey-body">Content in the survey body</h2>
<p>After the setup code chunk where we load the surveydown package, we have a series of pages (defined with <code>:::</code> fences) that include markdown-formatted text and survey questions (defined with <code><a href="https://pkg.surveydown.org/reference/sd_question.html">sd_question()</a></code>). You can modify any of this content as you wish to suit the needs of your survey.</p>
<p>In this demo, we have a few other examples included, like a conditionally displayed question (the <code>fav_fruit</code> question will not display if you choose “No” on the first question about liking fruit) as well as a question that skips people to the end (if you choose “blue” and not “red” on the <code>screening</code> page). The logic controlling the conditional display and skipping is defined with the <code><a href="https://pkg.surveydown.org/reference/sd_skip_if.html">sd_skip_if()</a></code> function in the <code>app.R</code> file.</p>
<p>None of this is absolutely necessary for a conjoint survey, but often times these are features that you may want to include, such as screening people out of the survey if they don’t qualify to take it, so we include it for demonstration purposes.</p>
</section><section id="defining-the-choice-questions" class="level2"><h2 class="anchored" data-anchor-id="defining-the-choice-questions">Defining the choice questions</h2>
<p>The central component of every conjoint survey is the set of randomized choice questions. To implement these in surveydown, we pre-define our choice questions in a design file that we later use in the survey to select randomized sets of choice questions to display each respondent.</p>
<p>We use the <a href="https://jhelvy.github.io/cbcTools/">cbcTools</a> package to create the pre-defined design file. The code to create the choice questions for this demo survey is in the <a href="https://github.com/surveydown-dev/template_conjoint_buttons/blob/main/code/1_make_choice_questions.R"><code>1_make_choice_questions.R</code></a> file in the demo repo. This code generates a data frame of randomized choice questions that we then save in the project directory as <code>choice_questions.csv</code>.</p>
</section><section id="implementing-the-choice-questions" class="level2"><h2 class="anchored" data-anchor-id="implementing-the-choice-questions">Implementing the choice questions</h2>
<p>The choice questions are implemented at the top of the <code>server()</code> function in the <code>app.R</code> file in the demo repo. This code does the following steps:</p>
<section id="read-in-the-design-file" class="level3"><h3 class="anchored" data-anchor-id="read-in-the-design-file">1. Read in the design file</h3>
<p>Pretty straightforward - this is one line to read in the <code>choice_questions.csv</code> design file that we saved in the project folder.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">design</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_csv</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"choice_questions.csv"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
</section><section id="sample-and-store-a-random-respondent-id" class="level3"><h3 class="anchored" data-anchor-id="sample-and-store-a-random-respondent-id">2. Sample and store a random respondent ID</h3>
<p>Since we want each respondent to see a different set of choice questions, we randomly sample a respondent ID from the set of all respondent IDs in the design file. We also need to keep track of this and store it in our response data so that later we can know what each respondent was actually shown.</p>
<p>Since this is a value that we generated in the server (and not a value from a survey question to a respondent), we have to manually add it to the survey response data using <code><a href="https://pkg.surveydown.org/reference/sd_store_value.html">sd_store_value()</a></code>. Here we modified the name so that in the resulting survey data the column name will be <code>"respID"</code>.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample a random respondentID</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">respondentID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/sample.html">sample</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">design</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">respID</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Store the respondentID</span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_store_value</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">respondentID</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"respID"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
</section><section id="filter-the-design-for-the-respondentid" class="level3"><h3 class="anchored" data-anchor-id="filter-the-design-for-the-respondentid">3. Filter the design for the respondentID</h3>
<p>We create a subset dataframe called <code>df</code> that stores only the rows for the randomly chosen respondent ID. We also append the <code>"images/"</code> string onto the values in the <code>image</code> column as this will create the relative path to the images in our survey, e.g.&nbsp;<code>"images/fuji.jpg"</code> (all the images we show are in the <code>"images"</code> folder in the repo).</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Filter for the rows for the chosen respondentID</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">design</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span>  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">respID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">respondentID</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span>  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>image <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/paste.html">paste0</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"images/"</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">image</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
</section><section id="define-a-function-to-create-question-options" class="level3"><h3 class="anchored" data-anchor-id="define-a-function-to-create-question-options">4. Define a function to create question options</h3>
<p>This is the most complex component in the server logic. Here we created a function that takes a dataframe and returns a named vector defining the options to show in each choice question. In this case, we only have 3 options per choice question, so each time we call this function we will use a small dataframe that has just 3 rows defining the 3 choice alternatives in a single choice question.</p>
<p>The function does several things. First, it extracts three single-row data frames that store the values of each of the 3 alternatives (<code>alt1</code>, <code>alt2</code>, and <code>alt3</code>). It then creates an <code>options</code> vector that has just 3 values: <code>"option_1"</code>, <code>"option_2"</code>, and <code>"option_3"</code>. Then we have to define the names of each of those options. Remember that the <em>values</em> in the <code>options</code> vector are what gets stored in our resulting survey data based on what the respondent chooses, but the <em>names</em> are what respondents see. So in the context of a choice survey like this, we need to embed all of the attributes and their levels in the names of the <code>options</code> vector.</p>
<p>We use the <code>glue()</code> function to easily inject the values stored in <code>alt1</code>, <code>alt2</code>, and <code>alt3</code> into our labels. The <code>glue()</code> function is similar to <code><a href="https://rdrr.io/r/base/paste.html">paste()</a></code> in that is just concatenates object values into a string, but it has an easier syntax to work with. Anything inside <code><a href="https://rdrr.io/r/base/Paren.html">{}</a></code> brackets is evaluated, and the resulting value is inserted into the string. So for example, the line <code>glue("1 plus 1 equals {1+1}")</code> would produce the string <code>"1 plus 1 equals 2"</code>.</p>
<p>In our case, we’re including some html code to insert an image of the apple type (<code>&lt;img src='{alt1$image}' width=100&gt;</code>), the apply type itself (<code>**Type**: {alt1$type}</code>), and the apple price (<code>**Price**: $ {alt1$price} / lb</code>).</p>
<p>Notice also that we’re mixing markdown (e.g.&nbsp;<code>**Option 1**</code>) and html (e.g.&nbsp;<code>&lt;br&gt;</code>), which will all get rendered into proper html in the resulting shiny app. The full function looks like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Function to create the labels for a choice question</span></span>
<span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># based on the values in df</span></span>
<span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">make_cbc_options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span>  <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">alt1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">altID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span>  <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">alt2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">altID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span>  <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">alt3</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">altID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span>  <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"option_1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"option_2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"option_3"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span>  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/names.html">names</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glue</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Option 1**&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    &lt;img src='{alt1$image}' width=100&gt;&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Type**: {alt1$type}&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Price**: $ {alt1$price} / lb&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Freshness**: {alt1$freshness}</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  "</span></span>
<span>    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span>,</span>
<span>    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glue</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Option 2**&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    &lt;img src='{alt2$image}' width=100&gt;&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Type**: {alt2$type}&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Price**: $ {alt2$price} / lb&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Freshness**: {alt2$freshness}</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  "</span></span>
<span>    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span>,</span>
<span>    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glue</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Option 3**&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    &lt;img src='{alt3$image}' width=100&gt;&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Type**: {alt3$type}&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Price**: $ {alt3$price} / lb&lt;br&gt;</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    **Freshness**: {alt3$freshness}</span></span>
<span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  "</span></span>
<span>    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span>  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span>  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;"><a href="https://rdrr.io/r/base/function.html">return</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</div>
</section><section id="create-the-options-for-each-choice-question" class="level3"><h3 class="anchored" data-anchor-id="create-the-options-for-each-choice-question">5. Create the options for each choice question</h3>
<p>One of the benefits of making the function the way we did in the previous step is that we can now easily call it to generate the option vector for each of the 6 choice questions in <code>df</code>:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create the options for each choice question</span></span>
<span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc1_options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_cbc_options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">qID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc2_options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_cbc_options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">qID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc3_options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_cbc_options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">qID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc4_options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_cbc_options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">qID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc5_options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_cbc_options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">qID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc6_options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_cbc_options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">qID</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
</section><section id="create-each-choice-question-6-in-total" class="level3"><h3 class="anchored" data-anchor-id="create-each-choice-question-6-in-total">6. Create each choice question (6 in total)</h3>
<p>Finally, we now have everything we need to generate each choice question. Here we’re using the <code>mc_buttons</code> question type so that the labels we generated will be displayed on a large button, which looks good both on a computer and phone. We give the question a unique <code>id</code> (e.g.&nbsp;<code>cbc_q1</code>), and a label, and then set the <code>option</code> to the corresponding option vector we defined above.</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  type   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mc_buttons'</span>,</span>
<span>  id     <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'cbc_q1'</span>,</span>
<span>  label  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(1 of 6) If these were your only options, which would you choose?"</span>,</span>
<span>  option <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc1_options</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ...and 5 more questions like this</span></span></code></pre></div></div>
</div>
<p>Remember that since the labels in the options are being <em>dynamically</em> generated on each new session (each respondent), they have to be created in the server, not in the main survey body. As a result, the <code><a href="https://pkg.surveydown.org/reference/sd_question.html">sd_question()</a></code> function must also be created in the server code (if you put this code in the main body, only one random set of choice options will be generated, and they’ll be the same for everyone).</p>
<p>To display each question in the survey body, we use <code>sd_output("id", type = "question")</code>, changing <code>id</code> to each corresponding choice question we created. In the demo <code>survey.qmd</code> file, you’ll see that there are 6 choice questions displayed in the main survey body (each on their own page), and each of those 6 questions are defined in the <code>server()</code> function in the <code>app.R</code> file.</p>
<p>When rendered, a choice question will look like this, with the values matching whatever alternative was chosen in the design file:</p>
<div class="cell">
<div class="cell-output-display">
<div id="container-cbc_q1" data-question-id="cbc_q1" class="question-container" style="width: 100%;" oninput="Shiny.setInputValue('cbc_q1_interacted', true, {priority: 'event'});" onclick="Shiny.setInputValue('cbc_q1_interacted', true, {priority: 'event'});">
<div class="form-group shiny-input-container shiny-input-radiogroup shiny-input-container-inline">
<label class="control-label" id="cbc_q1-label" for="cbc_q1"><p>(1 of 6) If these were your only options, which would you choose?</p>
</label>
<br><div id="cbc_q1" class="radio-group-buttons">
<div aria-labelledby="cbc_q1-label" class="btn-group btn-group-container-sw" data-toggle="buttons">
<input type="radio" autocomplete="off" id="cbc_q11" name="cbc_q1" value="option_1" class="btn-check"><label class="btn radiobtn btn-outline-primary" for="cbc_q11"><strong>Option 1</strong><br><img src="https://www.surveydown.org/blog/2024-08-28-choice-based-conjoint-surveys-with-surveydown/images/honeycrisp.jpg" width="100"><br><strong>Type</strong>: Honeycrisp<br><strong>Price</strong>: $ 1 / lb<br><strong>Freshness</strong>: Average</label>
<input type="radio" autocomplete="off" id="cbc_q12" name="cbc_q1" value="option_2" class="btn-check"><label class="btn radiobtn btn-outline-primary" for="cbc_q12"><strong>Option 2</strong><br><img src="https://www.surveydown.org/blog/2024-08-28-choice-based-conjoint-surveys-with-surveydown/images/fuji.jpg" width="100"><br><strong>Type</strong>: Fuji<br><strong>Price</strong>: $ 3 / lb<br><strong>Freshness</strong>: Excellent</label>
<input type="radio" autocomplete="off" id="cbc_q13" name="cbc_q1" value="option_3" class="btn-check"><label class="btn radiobtn btn-outline-primary" for="cbc_q13"><strong>Option 3</strong><br><img src="https://www.surveydown.org/blog/2024-08-28-choice-based-conjoint-surveys-with-surveydown/images/redDelicious.jpg" width="100"><br><strong>Type</strong>: Red Delicious<br><strong>Price</strong>: $ 2.5 / lb<br><strong>Freshness</strong>: Average</label>
</div>
</div>
<script>
            $(document).on('click', '#cbc_q1 .btn', function() {
                Shiny.setInputValue('cbc_q1_interacted', true, {priority: 'event'});
                // Small delay to allow button state to update
                setTimeout(function() {
                    var selectedValue = '';
                    // Look for checked radio input within the container
                    var checkedInput = $('#cbc_q1 input[type="radio"]:checked');
                    if (checkedInput.length > 0) {
                        selectedValue = checkedInput.val();
                    }
                    Shiny.setInputValue('cbc_q1', selectedValue, {priority: 'event'});
                }, 50);
            });
        </script>
</div>
<span class="hidden-asterisk">*</span>
</div>
</div>
</div>
<p><br></p>
<p>And that’s it! You now have 6 randomized choice questions!</p>
</section></section><section id="buttons-versus-tables" class="level2"><h2 class="anchored" data-anchor-id="buttons-versus-tables">Buttons versus tables</h2>
<p>In the example above, the conjoint choice questions are displayed as “buttons” where all the information for each alternative is shown as a button. This works particularly well for mobile phone applications where the user may need to scroll vertically to see each option.</p>
<p>An alternative is to use a table layout where each column represents an alternative and the row names explain the attribute. This takes a little manipulation to get it right, but the key concept is to use <code><a href="https://rdrr.io/pkg/knitr/man/kable.html">kable()</a></code> to display the transpose of the <code>df</code> data frame (the subset of rows for a particular respondent). We also use the wonderful <a href="https://cran.r-project.org/web/packages/kableExtra/vignettes/awesome_table_in_html.html">kableExtra</a> package to modify some of the table stying. We don’t explain this code in detail in this blog post, but the gist of what we’re doing here is creating a dataframe with our alternatives and displaying it as a table with <code><a href="https://rdrr.io/pkg/knitr/man/kable.html">kable()</a></code>.</p>
<p>The main function doing this work in the <a href="https://surveydown.org/templates/conjoint_tables">conjoint table</a> template is the <code>make_cbc_table()</code> function, which looks like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;"><a href="https://rdrr.io/r/base/library.html">library</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;"><a href="https://dplyr.tidyverse.org">dplyr</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;"><a href="https://rdrr.io/r/base/library.html">library</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;"><a href="http://haozhu233.github.io/kableExtra/">kableExtra</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Function to create the options table for a given choice question</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">make_cbc_table</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span>  <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">alts</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span>    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://dplyr.tidyverse.org/reference/mutate.html">mutate</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>      price <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/paste.html">paste</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scales</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://scales.r-lib.org/reference/dollar_format.html">dollar</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">price</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/ lb"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span>,</span>
<span>      image <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/paste.html">paste0</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'&lt;img src="'</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">image</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'" width=100&gt;'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span>    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span>    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Make nicer attribute labels</span></span>
<span>    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://dplyr.tidyverse.org/reference/select.html">select</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>      `Option:` <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">altID</span>,</span>
<span>      ` ` <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">image</span>,</span>
<span>      `Price:` <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">price</span>,</span>
<span>      `Type:` <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">type</span>,</span>
<span>      `Freshness:` <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">freshness</span></span>
<span>    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span>  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/row.names.html">row.names</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">alts</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Drop row names</span></span>
<span></span>
<span>  <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">table</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/pkg/kableExtra/man/kbl.html">kbl</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/t.html">t</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">alts</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span>, escape <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|&gt;</span></span>
<span>    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/pkg/kableExtra/man/kable_styling.html">kable_styling</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>      bootstrap_options <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"striped"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"hover"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"condensed"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span>,</span>
<span>      full_width <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>,</span>
<span>      position <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"center"</span></span>
<span>    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span>  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span>    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">table</span></span>
<span>  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</div>
<p>It is important to note that the table just shows the options, but it doesn’t allow respondents to indicate their choice. So we still need to create a basic choice question like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc1_options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"option_1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"option_2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"option_3"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/names.html">names</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc1_options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Option 1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Option 2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Option 3"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  type   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mc_buttons'</span>,</span>
<span>  id     <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'cbc_q1'</span>,</span>
<span>  label  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"(1 of 6) If the above options were your only options, which would you choose?"</span>,</span>
<span>  option <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cbc1_options</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
<div class="cell-output-display">
<div id="container-cbc_q1" data-question-id="cbc_q1" class="question-container" style="width: 100%;" oninput="Shiny.setInputValue('cbc_q1_interacted', true, {priority: 'event'});" onclick="Shiny.setInputValue('cbc_q1_interacted', true, {priority: 'event'});">
<div class="form-group shiny-input-container shiny-input-radiogroup shiny-input-container-inline">
<label class="control-label" id="cbc_q1-label" for="cbc_q1"><p>(1 of 6) If the above options were your only options, which would you choose?</p>
</label>
<br><div id="cbc_q1" class="radio-group-buttons">
<div aria-labelledby="cbc_q1-label" class="btn-group btn-group-container-sw" data-toggle="buttons">
<input type="radio" autocomplete="off" id="cbc_q11" name="cbc_q1" value="option_1" class="btn-check"><label class="btn radiobtn btn-outline-primary" for="cbc_q11">Option 1</label>
<input type="radio" autocomplete="off" id="cbc_q12" name="cbc_q1" value="option_2" class="btn-check"><label class="btn radiobtn btn-outline-primary" for="cbc_q12">Option 2</label>
<input type="radio" autocomplete="off" id="cbc_q13" name="cbc_q1" value="option_3" class="btn-check"><label class="btn radiobtn btn-outline-primary" for="cbc_q13">Option 3</label>
</div>
</div>
<script>
            $(document).on('click', '#cbc_q1 .btn', function() {
                Shiny.setInputValue('cbc_q1_interacted', true, {priority: 'event'});
                // Small delay to allow button state to update
                setTimeout(function() {
                    var selectedValue = '';
                    // Look for checked radio input within the container
                    var checkedInput = $('#cbc_q1 input[type="radio"]:checked');
                    if (checkedInput.length > 0) {
                        selectedValue = checkedInput.val();
                    }
                    Shiny.setInputValue('cbc_q1', selectedValue, {priority: 'event'});
                }, 50);
            });
        </script>
</div>
<span class="hidden-asterisk">*</span>
</div>
</div>
</div>
<p>The final result is a set of choice questions that each look something like this:</p>
<center>
<img src="https://www.surveydown.org/blog/2024-08-28-choice-based-conjoint-surveys-with-surveydown/images/cbc_table.png" width="500">
</center>
</section><section id="preview-and-check" class="level2"><h2 class="anchored" data-anchor-id="preview-and-check">Preview and check</h2>
<p>The rest of the <code>server()</code> function in the <code>app.R</code> file has the remaining components we need, like any conditional display or skip logic. This is all standard features of any surveydown survey, so we won’t cover them in detail here and instead direct you to the <a href="https://surveydown.org/docs.html">documentation</a> for details.</p>
<p>But before you go live, it’s a good idea to do some quick testing. You can test your survey even without having it connected to a database by setting <code>ignore = TRUE</code> in the <code><a href="https://pkg.surveydown.org/reference/sd_db_connect.html">sd_db_connect()</a></code> function. Of course, you probably should also test it after connecting it to a database to ensure that responses are being properly stored.</p>
<p>When testing, you might get an error - don’t panic! Read the terminal output carefully and debug. There’s a good chance you may have missed a bug somewhere in your server code. Look in your <code>app.R</code> file to see if you can spot the error.</p>
</section><section id="getting-the-data" class="level2"><h2 class="anchored" data-anchor-id="getting-the-data">Getting the data</h2>
<p>Once your survey is live and you start collecting responses, you can easily access your data with the <code><a href="https://pkg.surveydown.org/reference/sd_get_data.html">sd_get_data()</a></code> function. This is typically done in a separate R file (e.g., see <a href="https://github.com/surveydown-dev/template_conjoint_buttons/blob/main/code/2_get_raw_data.R">here</a>), which might look something like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;"><a href="https://rdrr.io/r/base/library.html">library</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org">surveydown</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Connect to database</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">db</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_db_connect.html">sd_db_connect</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pull in the data</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_get_data.html">sd_get_data</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">db</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>For this to work, you will first have to make sure you’ve set up your database connection using <code>sd_db_config</code> (see <a href="https://surveydown.org/docs/storing-data">here</a> for more).</p>
<p>And that’s it! We hope this post was helpful, and do go check out the <a href="https://surveydown.org/templates/conjoint_buttons">conjoint buttons</a> and <a href="https://surveydown.org/templates/conjoint_tables">conjoint table</a> templates to try out the demos yourself!</p>


</section><a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a><div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>
<ol>
<li id="fn1"><p>Yes, people have <a href="https://www.emerald.com/insight/content/doi/10.1108/00070709610150879/full/html">actually done conjoint surveys on fruit</a> before.↩︎</p></li>
</ol></section></div> ]]></description>
  <category>R</category>
  <category>tutorial</category>
  <category>conjoint</category>
  <guid>https://www.surveydown.org/blog/2024-08-28-choice-based-conjoint-surveys-with-surveydown/</guid>
  <pubDate>Wed, 28 Aug 2024 00:00:00 GMT</pubDate>
  <media:content url="https://www.surveydown.org/blog/2024-08-28-choice-based-conjoint-surveys-with-surveydown/images/banner.png" medium="image" type="image/png" height="96" width="144"/>
</item>
<item>
  <title>Introducing surveydown: A markdown-based framework for generating surveys with Quarto and shiny</title>
  <dc:creator>John Paul Helveston</dc:creator>
  <link>https://www.surveydown.org/blog/2024-08-21-introducing-surveydown/</link>
  <description><![CDATA[ <center>
<img src="https://www.surveydown.org/blog/2024-08-21-introducing-surveydown/logo.png" style="max-width: 200px; width: 100%;">
</center>
<p><br></p>
<div class="callout callout-style-default callout-important callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>This post was made just after launching surveydown. Much of the platform architecture has changed since then, so check the <a href="https://surveydown.org/docs.html">documentation</a> for the latest correct information.</strong></p>
</div>
</div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>Note:</strong> This post is largely a copy of the <a href="https://www.jhelvy.com/blog/2024-08-10-introducing-surveydown/">a similar post</a> I made on my personal website, with some minor edits.</p>
</div>
</div>
<p>This post introduces the {surveydown} R package, a new way to design surveys using markdown, R, Quarto, and shiny. The idea for this platform has been brewing for a while (see <a href="https://jhelvy.com/blog/2023-04-06-markdown-surveys/">this blog post</a> for more on the motivation for this project), but now the package is finally here!</p>
<p>In this post, I’m going to show you a quick overview of the {surveydown} R package for making markdown-based surveys as well as a little about <em>why</em> we built surveydown.</p>
<section id="a-new-way-to-design-surveys" class="level1"><h1>A new way to design surveys</h1>
<p><a href="https://surveydown.org/">surveydown</a> is a flexible platform for making surveys in <i class="fa-brands fa-r-project" aria-label="r-project"></i> using three open source technologies: <a href="https://quarto.org/">Quarto</a>, <a href="https://shiny.posit.co/">shiny</a>, and <a href="https://supabase.com/">supabase</a>. The package is still in development, but you can already use it to create surveys.</p>
<br><center>
<img src="https://www.surveydown.org/blog/2024-08-21-introducing-surveydown/technologies.png" style="max-width: 600px; width: 100%;">
</center>
<p><br></p>
<p>The basic concept is this:</p>
<ol type="1">
<li>Design your survey as a <a href="https://quarto.org/docs/dashboards/interactivity/shiny-r.html">Quarto shiny document</a> using markdown and R code.</li>
<li>Render your doc into a <a href="https://shiny.posit.co/">shiny</a> app that can be hosted online and sent to respondents.</li>
<li>Store your survey responses in a <a href="https://supabase.com/">supabase</a> database.</li>
</ol>
<p>In surveydown, your entire survey is designed using markdown and R code in a single Quarto document. There is no GUI or drag-and-drop interface - simply write plain text (markdown and R code) and boom - you have a survey!</p>
<p>The <a href="https://pkg.surveydown.org/">{surveydown} package</a> provides a set of functions for defining the survey content and control logic. Each function starts with <code>sd_</code> to make them easy to identify. You can add content to your survey using markdown formatting, or in RStudio you can edit with the visual editor. Survey questions are defined in R code chunks with the <code>sd_question()</code> function. Pages are defined using fences (<code>:::</code>), and navigation buttons handled with the <code>sd_next()</code> function. You can modify the control logic in the server code chunk (the last code chunk at the bottom of the .qmd file) with the <code>sd_config()</code> function, and you can configure the database with the <code>sd_database()</code>.</p>
<p>The <a href="https://surveydown.org/docs.html">documentation</a> has many more details on all of this, and later in this post I’ll give a quick overview of a few of these features. But first, let me tell you a little about <em>why</em> we decided to build surveydown.</p>
</section><section id="why-did-we-build-surveydown" class="level1"><h1>Why did we build surveydown?</h1>
<blockquote class="blockquote">
<p>Do we really need another survey platform?</p>
</blockquote>
<p>Like many researchers who do a lot of survey work, I’ve been frustrated with most survey platforms available. Commerical platforms like Qualtrics and SurveyMonkey are great, but they are expensive and are difficult to version control, and collaboration with others is near impossible, especially if your collaborator doesn’t have a license of their own. They also don’t allow me to own my own survey data, meaning I always am at the mercy of the platform owner. And the features are often limited. It’s not easy to do more complex things like randomization, conditional display, etc.</p>
<p>The only other open-source survey platform I have used is <a href="https://formr.org/">formr</a>, which is a very powerful platform, but it is rather clunky to use (you define your survey in Google sheet cells…there’s a learning curve), and it is not as easy to edit as a simple markdown file.</p>
<p>What we’ve come up with is a survey platform that is flexible, <em>relatively</em> easy to use, and built entirely with open-source technologies. I think it solves a lot of problems, and hopefully someone out there will find it useful.</p>
<section id="open-source" class="level2"><h2 class="anchored" data-anchor-id="open-source">Open source</h2>
<p>surveydown is built entirely with open-source technologies, making it transparent and customizable. Best of all, no expensive licenses! Just install and use it!</p>
</section><section id="own-your-data" class="level2"><h2 class="anchored" data-anchor-id="own-your-data">Own your data</h2>
<p>With surveydown, you retain full ownership and control of your survey data. The responses are stored in your own Supabase database, ensuring that you have complete access to the data. This is particularly important for researchers dealing with sensitive information or those who need to comply with specific data protection regulations. We’re still working on enabling you to use your own hosted database, which will provide even more flexibility.</p>
</section><section id="ease-of-editing" class="level2"><h2 class="anchored" data-anchor-id="ease-of-editing">Ease of editing</h2>
<p>Designing a survey in surveydown is a pretty straightforward process. The markdown-based approach allows for quick modifications and easy navigation through your survey. And since it’s built on <a href="https://quarto.org/">Quarto</a>, you can use all of the features of Quarto to make your survey look great, like changing the theme, adding custom CSS, etc. You can also easily preview your survey as you edit it, and even run your survey locally to test it out before you deploy it, either with a button click in RStudio or with a <code>quarto serve</code> command in the terminal.</p>
</section><section id="did-i-mention-you-can-run-r-code-in-your-survey" class="level2"><h2 class="anchored" data-anchor-id="did-i-mention-you-can-run-r-code-in-your-survey">Did I mention you can run R code in your survey?</h2>
<p>Every surveydown survey uses R code chunks for questions. But you can also insert R code for all sorts of other things. For example, if you wanted to randomize the values shown in a question, you could write some R code for that. Want to insert a plot of something? Write a little ggplot code. You can also add interactive components to your surveys, such as showing a respondent how their responses compare to others in real time.</p>
</section><section id="easy-version-control-and-collaboration" class="level2"><h2 class="anchored" data-anchor-id="easy-version-control-and-collaboration">Easy version control and collaboration</h2>
<p>Because the entire survey is defined in a single plain text file, surveydown naturally integrates with version control systems like Git. This allows you to track changes over time, collaborate with team members, and maintain a clear history of your survey’s development.</p>
</section><section id="reproducible" class="level2"><h2 class="anchored" data-anchor-id="reproducible">Reproducible</h2>
<p>Surveydown promotes reproducible research by allowing you to define your entire survey in a single, self-contained plain text document. This has a ton of benefits:</p>
<ul>
<li>Want someone else to be able to reproduce your experiment? Just give them the .qmd file and any other files they need (e.g., images, data, etc.), and they can reproduce your survey on their own computer.</li>
<li>Want to print out your survey for an appendix? Render the survey with all pages visible then print it to pdf.</li>
<li>Want others to see your survey live? Just set the database into pause mode and your survey will function without recording any responses.</li>
</ul>
<p>Reproducibility is something we had in mind from the start with this project, and we’ve tried to make it as easy as possible for your surveydown surveys to be fully reproducible.</p>
</section></section><section id="introduction-to-surveydown" class="level1"><h1>Introduction to surveydown</h1>
<section id="getting-started" class="level2"><h2 class="anchored" data-anchor-id="getting-started">Getting started</h2>
<p>After getting everything <a href="https://surveydown.org//docs/getting-started.html#install">installed</a>, we recommend starting with a template survey project. To do so, run the following in the R console:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">surveydown</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://pkg.surveydown.org/reference/sd_create_survey.html">sd_create_survey</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"path/to/folder"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>This will create a folder with the following files:</p>
<ul>
<li>
<code>example.qmd</code>: a template survey you should edit.</li>
<li>
<code>example.Rproj</code>: An RStudio project file (helpful if you’re working in RStudio)</li>
<li>
<code>_extensions</code>: A folder with the surveydown Quarto extension needed to make everything work (don’t modify this).</li>
</ul>
<p>If you have the example open in RStudio, you can click the “Run document” button, or in your terminal run <code>quarto serve example.qmd</code>. Either approach should render the example survey into a shiny app that you can preview in a browser. Don’t worry just yet about setting up your database or making the survey live - for now, we’re going to focus on designing the survey and running it locally to preview it. The example survey should look like this:</p>
<center>
<img src="https://www.surveydown.org/blog/2024-08-21-introducing-surveydown/example.png" style="max-width: 700px; width: 100%;">
</center>
</section><section id="adding-pages" class="level2"><h2 class="anchored" data-anchor-id="adding-pages">Adding pages</h2>
<p>In surveydown, pages are delineated using “fences”, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span> {<span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#welcome .sd-page}</span></span>
<span id="cb2-2"></span>
<span id="cb2-3">Page <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> content here</span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span>
<span id="cb2-6"></span>
<span id="cb2-7"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">:::</span> {<span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#page2 .sd-page}</span></span>
<span id="cb2-8"></span>
<span id="cb2-9">Page <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> content here</span>
<span id="cb2-10"></span>
<span id="cb2-11"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span></code></pre></div></div>
</div>
<p>As you can see, we use three colon symbols <code>:::</code>, called a “fence”, to mark the start and end of pages. This notation is commonly used in Quarto for a variety of use cases, like defining <a href="https://quarto.org/docs/authoring/figures.html#subfigures">subfigures</a> in images.</p>
<p>In the starting fence, you need to define a page name (e.g.&nbsp;<code>welcome</code> and <code>page2</code> in the example above) and you need to define the class as <code>.sd-page</code>. Then anything you put between the page fences will appear on that page.</p>
<p>To navigate to the next page, you need to insert a <code>sd_next()</code> function call inside a code chunk, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb3-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_next</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">next_page =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'page2'</span>)</span>
<span id="cb3-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
</div>
<p>The above code chunk will create a “Next” button that goes on to page 2 that looks like this:</p>
<div class="cell">
<div class="cell-output-display">
<div data-next-page="page2" style="margin-top: 1rem; margin-bottom: 0.5rem;">
<button class="btn btn-default action-button sd-enter-button" id="page_id_next" onclick="Shiny.setInputValue('next_page', this.parentElement.getAttribute('data-next-page'));" style="display: block; margin: auto;" type="button"><span class="action-label">Next</span></button>
</div>
</div>
</div>
<p>You would need to place the code chunk in between the <code>:::</code> fences of the <code>welcome</code> page in order to have a “Next” button that goes on to page 2. You can also send the user to other pages by just changing the <code>next_page</code> argument. Finally, you can also change the label of the button by changing the <code>label</code> argument, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb4-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb4-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_next</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">next_page =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'page2'</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Next page'</span>)</span>
<span id="cb4-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
</div>
<div class="cell">
<div class="cell-output-display">
<div data-next-page="page2" style="margin-top: 1rem; margin-bottom: 0.5rem;">
<button class="btn btn-default action-button sd-enter-button" id="page_id_next" onclick="Shiny.setInputValue('next_page', this.parentElement.getAttribute('data-next-page'));" style="display: block; margin: auto;" type="button"><span class="action-label">Next page</span></button>
</div>
</div>
</div>
</section><section id="adding-questions" class="level2"><h2 class="anchored" data-anchor-id="adding-questions">Adding questions</h2>
<p>Every survey question is created using the <code>sd_question()</code> function inside a code chunk. The question type is defined by the <code>type</code> argument. For example, to add a multiple choice question, you could insert the following code chunk:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb5-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span>(</span>
<span id="cb5-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type  =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mc'</span>,</span>
<span id="cb5-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id    =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'penguins'</span>,</span>
<span id="cb5-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Which is your favorite type of penguin?"</span>,</span>
<span id="cb5-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb5-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Adélie'</span>    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'adelie'</span>,</span>
<span id="cb5-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Chinstrap'</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'chinstrap'</span>,</span>
<span id="cb5-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Gentoo'</span>    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'gentoo'</span></span>
<span id="cb5-10">  )</span>
<span id="cb5-11">)</span>
<span id="cb5-12"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
</div>
<p>The above code chunk will create a multiple choice question that looks like this:</p>
<div class="cell">
<div class="cell-output-display">
<div id="container-penguins" data-question-id="penguins" class="question-container" style="width: 500;" oninput="Shiny.setInputValue('penguins_interacted', true, {priority: 'event'});" onclick="Shiny.setInputValue('penguins_interacted', true, {priority: 'event'});">
<div id="penguins" class="form-group shiny-input-radiogroup shiny-input-container" aria-labelledby="penguins-label">
<label class="control-label" id="penguins-label" for="penguins"><p>Which is your favorite type of penguin?</p>
</label>
<div class="shiny-options-group">
<div class="radio">
<label>
<input type="radio" name="penguins" value="adelie"><span>Adélie</span>
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="penguins" value="chinstrap"><span>Chinstrap</span>
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="penguins" value="gentoo"><span>Gentoo</span>
</label>
</div>
</div>
</div>
<span class="hidden-asterisk">*</span>
</div>
</div>
</div>
<p><br></p>
<p>The <code>sd_question()</code> function can be used to create a variety of <a href="https://surveydown.org/docs/question-types.html">question types</a>, like text input, select drop down choices, and more by changing the <code>type</code> argument.</p>
<p>The function has many other arguments for customizing the look and feel of the question (e.g., <code>height</code> and <code>width</code>, etc.).</p>
</section><section id="the-server-chunk" class="level2"><h2 class="anchored" data-anchor-id="the-server-chunk">The server chunk</h2>
<p>At the very bottom of the .qmd file is a special “server” code chunk (that’s the <code>#| context: server</code> bit) that defines the app server. This is where you can customize and control the survey flow logic as well as where you define the database that will store the survey response data. It looks like this:</p>
<div class="cell" data-context="server">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb6-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb6-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| context: server</span></span>
<span id="cb6-3"></span>
<span id="cb6-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the database settings</span></span>
<span id="cb6-5">db <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_database</span>()</span>
<span id="cb6-6"></span>
<span id="cb6-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the configuration settings</span></span>
<span id="cb6-8">config <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_config</span>()</span>
<span id="cb6-9"></span>
<span id="cb6-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The sd_server() function initiates your survey - don't change this</span></span>
<span id="cb6-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_server</span>(</span>
<span id="cb6-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input   =</span> input,</span>
<span id="cb6-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">session =</span> session,</span>
<span id="cb6-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">config  =</span> config,</span>
<span id="cb6-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">db      =</span> db</span>
<span id="cb6-16">)</span>
<span id="cb6-17"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
</div>
<p>The <code>sd_database()</code> function is where you set up your database. The <code>sd_server()</code> function makes everything run, which you can safely ignore - just don’t change it and all will be good!</p>
<p>The middle part (the <code>sd_config()</code> function) is where you can define custom control logic for the survey, such as <em>conditional display</em> (conditionally displaying a question based on responses to questions), or <em>conditional skip</em> (conditionally sending the respondent to a page based on responses to questions).</p>
</section><section id="going-live" class="level2"><h2 class="anchored" data-anchor-id="going-live">Going live!</h2>
<p>Once you are happy with your survey, you can deploy it live to any server of your choice. Since it’s a shiny app, you can <a href="https://surveydown.org/docs/deployment.html#deploying-to-shinyapps.io">deploy it to shinyapps.io</a> for free!</p>
</section></section><section id="features" class="level1"><h1>Features</h1>
<p>Since surveydown is built on top of Shiny, it provides tremendous flexibility in terms of what you can do with your survey. Below are a few examples of some commons things you may want to do with your survey.</p>
<section id="conditional-display" class="level2"><h2 class="anchored" data-anchor-id="conditional-display">Conditional display</h2>
<p>Let’s say we had a fourth option for “other” in our multiple choice question about penguins. If the respondent chose it, you may want a second question to popup that allows them to specify the other penguin type. To implement this, you would need to define both questions, e.g.:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb7-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb7-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span>(</span>
<span id="cb7-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type  =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mc'</span>,</span>
<span id="cb7-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id    =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'penguins'</span>,</span>
<span id="cb7-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Which is your favorite type of penguin?"</span>,</span>
<span id="cb7-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb7-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Adélie'</span>    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'adelie'</span>,</span>
<span id="cb7-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Chinstrap'</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'chinstrap'</span>,</span>
<span id="cb7-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Gentoo'</span>    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'gentoo'</span>,</span>
<span id="cb7-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Other'</span>     <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'other'</span></span>
<span id="cb7-11">  )</span>
<span id="cb7-12">)</span>
<span id="cb7-13"></span>
<span id="cb7-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span>(</span>
<span id="cb7-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type  =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text"</span>,</span>
<span id="cb7-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id    =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"penguins_other"</span>,</span>
<span id="cb7-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Please specify the other penguin type:"</span></span>
<span id="cb7-18">)</span>
<span id="cb7-19"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
</div>
<p>Then in the server code chunk, you could use the <code>show_if</code> argument to define that the <code>penguins_other</code> question would only be shown if the respondent chose the <code>other</code> option in the <code>penguins</code> question, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">config</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_config</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  show_if <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://tibble.tidyverse.org/reference/tribble.html">tribble</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">question_id</span>,  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">question_value</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">target</span>,</span>
<span>    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"penguins"</span>,    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"other"</span>,         <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"penguins_other"</span></span>
<span>  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>This will make the <code>penguins_other</code> question only appear if the respondent chose the <code>other</code> option in the <code>penguins</code> question, like this:</p>
<center>
<img src="https://www.surveydown.org/blog/2024-08-21-introducing-surveydown/show_if.gif" style="max-width: 600px; width: 100%; box-shadow: 0 8px 12px 0 rgba(0, 0, 0, 0.3); border: 1px solid #000; border-radius: 5px;">
</center>
<p><br></p>
<p>Here we’re using the <code><a href="https://tibble.tidyverse.org/reference/tribble.html">tibble::tribble()</a></code> function to define a data frame with three columns:</p>
<ul>
<li>
<code>question_id</code>: The <code>id</code> of the triggering question.</li>
<li>
<code>question_value</code>: The triggering value.</li>
<li>
<code>target</code>: The <code>id</code> of the target question to display.</li>
</ul>
<p>You don’t have to use <code><a href="https://tibble.tidyverse.org/reference/tribble.html">tibble::tribble()</a></code>, and in fact if you have a lot of <code>show_if</code> conditions, then you could create a csv file with all of your conditions in it and read it in to set the <code>show_if</code> conditions (just make sure the header has the same three column names), e.g.:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1">config <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_config</span>(</span>
<span id="cb9-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">show_if =</span> readr<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_csv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'path/to/show_if_conditions.csv'</span>)</span>
<span id="cb9-3">  )</span>
<span id="cb9-4"><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
</section><section id="conditional-skip" class="level2"><h2 class="anchored" data-anchor-id="conditional-skip">Conditional skip</h2>
<p>Often times you’ll want to screen people out of a survey based on responses to questions. For example, let’s say you only wanted to only include people who own a vehicle. On your first page (e.g., with page name <code>welcome</code>), you could screen out people who do <em>not</em> own a vehicle.</p>
<p>First, define a question about their vehicle ownership, e.g.:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb10-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span>(</span>
<span id="cb10-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type  =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mc'</span>,</span>
<span id="cb10-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id    =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vehicle_ownership'</span>,</span>
<span id="cb10-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">label =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Do you own your vehicle?"</span>,</span>
<span id="cb10-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">option =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(</span>
<span id="cb10-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Yes'</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'yes'</span>,</span>
<span id="cb10-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'No'</span>  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'no'</span></span>
<span id="cb10-9">  )</span>
<span id="cb10-10">)</span>
<span id="cb10-11"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div></div>
</div>
<p>Then in the server code chunk, you could use the <code>skip_if</code> argument in <code>sd_config()</code> to define the behavior of the next button on the <code>welcome</code> page, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">config</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_config</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  skip_if <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://tibble.tidyverse.org/reference/tribble.html">tribble</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">question_id</span>,        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">question_value</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">target</span>,</span>
<span>    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vehicle_ownership"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"no"</span>,            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"screenout"</span></span>
<span>  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>This sets up a condition where if the respondent chooses <code>no</code> on the <code>vehicle_ownership</code> question, they will be sent to a page named <code>screenout</code>. You could put such a page at the end of the survey, something like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span> {<span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#screenout .sd-page}</span></span>
<span id="cb12-2"></span>
<span id="cb12-3">Sorry, but you are not qualified to take our survey.</span>
<span id="cb12-4"></span>
<span id="cb12-5"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:::</span></span></code></pre></div></div>
</div>
<p>Notice that I don’t have a <code>sd_next()</code> on this screenout page. That is how you define an end point for the survey taker. If there’s no “Next” button, then they cannot navigate anywhere else, so the survey is over.</p>
</section><section id="required-responses" class="level2"><h2 class="anchored" data-anchor-id="required-responses">Required responses</h2>
<p>By default, no questions are required. However, you can make questions required by adding the question <code>id</code> to the <code>required</code> argument in <code>sd_config()</code>, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">config</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_config</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  required_questions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vehicle_ownership"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"penguins_other"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>This will make the respondent unable to proceed until they have answered the required questions. It will also place a red asterisk (*) next to the question label to indicate that the question is required.</p>
<p>You can also make all questions required by setting <code>all_questions_required = TRUE</code> like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">config</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_config</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  all_questions_required <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
</section><section id="reactivity" class="level2"><h2 class="anchored" data-anchor-id="reactivity">Reactivity</h2>
<p>One other feature that is particularly powerful is the ability to use R code in your survey via Shiny’s reactive programming. This allows you to make your survey more interactive and to use the full power of R to create custom functionality.</p>
<section id="demo-1-displaying-content-based-on-previous-responses" class="level3"><h3 class="anchored" data-anchor-id="demo-1-displaying-content-based-on-previous-responses">Demo 1: Displaying content based on previous responses</h3>
<p>Let’s say you wanted to create a survey that asked the respondent’s name, and then displayed a personalized message based on their name. You could do this by first asking their name:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  type  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text"</span>,</span>
<span>  id    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>,</span>
<span>  label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What is your name?"</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>Then you can use the <code>sd_display_value("name")</code> function to display the value of the <code>name</code> question in other parts of your survey. For example:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">Welcome, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">r sd_display_value("name")</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span></span></code></pre></div></div>
</div>
<p>Which would render as something like “Welcome, Dave!” (assuming the respondent entered “Dave” in the <code>name</code> question). This works because the <code>sd_display_value()</code> function is reactive, meaning it will update the display based on the respondent’s responses.</p>
</section><section id="demo-2-displaying-randomized-question-labels" class="level3"><h3 class="anchored" data-anchor-id="demo-2-displaying-randomized-question-labels">Demo 2: Displaying randomized question labels</h3>
<p>Let’s say you wanted to show a series of questions, but you wanted to randomize the labels shown for each question. You could do this by first defining a list of labels, and then using the <code>sd_question_reactive()</code> function to create a question that will display a random label from the list.</p>
<p>For example, let’s ask the respondent to rate different car brands from a random set of brands. You could first pre-define the randomized sets of brands for each respondent and store it as a csv file, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">brands</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Toyota"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Ford"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Chevrolet"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Honda"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Nissan"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tesla"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">design</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/data.frame.html">data.frame</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  respondent_id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/rep.html">rep</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, each <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span>,</span>
<span>  brand <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/unlist.html">unlist</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/lapply.html">lapply</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">x</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/sample.html">sample</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">brands</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, replace <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write_csv</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">design</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"design.csv"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>This would make a design file that looks like this:</p>
<div class="cell">
<div class="cell-output cell-output-stdout">
<pre><code>#&gt;   respondent_id     brand
#&gt; 1             1      Ford
#&gt; 2             1     Honda
#&gt; 3             1 Chevrolet
#&gt; 4             2    Toyota
#&gt; 5             2     Honda
#&gt; 6             2    Nissan</code></pre>
</div>
</div>
<p>Note that this would not be done in your survey.qmd file - it’s just a one-time thing to create the design (probably stored in an R file).</p>
<p>Then in your server code chunk, you could read in the design file and use it to randomize the labels for each question based on a randomly chosen respondent:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">design</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_csv</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"design.csv"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">resp_id</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/sample.html">sample</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">design</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">respondent_id</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df_resp</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">design</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/stats/filter.html">filter</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">respondent_id</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">resp_id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span></span>
<span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">options</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/c.html">c</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;"><a href="https://rdrr.io/r/base/names.html">names</a></span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">options</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">df_resp</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">brand</span></span>
<span></span>
<span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_question_reactive</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span>  type  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mc"</span>,</span>
<span>  id    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"brands"</span>,</span>
<span>  label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Which of these brands do you like best?"</span>,</span>
<span>  option <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">options</span></span>
<span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>Here the <code>sd_question_reactive()</code> function is used because the labels depend on the randomly chosen respondent. This means the labels will be different for each respondent.</p>
<p>Since this is a reactive question, <strong>this code must be placed inside the server code chunk</strong>, not where you want it to appear in the survey. To define where in the survey the question should appear, you use the <code>sd_display_question()</code> function with the <code>id</code> set to the same value as the <code>id</code> in the <code>sd_question_reactive()</code> function, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_display_question</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"brands"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
<p>Now the <code>brands</code> question will be displayed in the survey where you put this code chunk.</p>
<p>Note that all question responses are automatically saved to the database, but if you wanted to store some other value (e.g.&nbsp;the randomly chosen <code>respondent_id</code>), you could do that with the <code>sd_store_value()</code> function, like this:</p>
<div class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb21" style="background: #f1f3f5;"><pre class="downlit sourceCode r code-with-copy"><code class="sourceCode R"><span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd_store_value</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">resp_id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div></div>
</div>
</section></section></section><section id="how-we-built-it" class="level1"><h1>How we built it</h1>
<p>Before I wrap up, I just want to say that I am absolutely amazed at the time we live in. I have had this idea in mind for many years, but I’m not a web developer, and I never could come up with a way to make it happen. That was actually what motivated me to write my <a href="https://jhelvy.com/blog/2023-04-06-markdown-surveys/">previous blog post</a> - it was a call for help from others!</p>
<p>But two things happened relatively recently that made it possible:</p>
<ol type="1">
<li>The rise of Quarto</li>
<li>The rise of LLMs</li>
</ol>
<p>After I switched my website over from distill to Quarto, I began to learn more and more about how powerful Quarto really is for building things on the web. Then I saw the <a href="https://quarto.org/docs/dashboards/interactivity/shiny-r.html">Quarto shiny document</a> framework and I immediately thought that this just might be the missing piece I needed to make surveydown a reality. It does all the legwork of converting markdown and R code into a shiny app.</p>
<p>Of course, implementing this idea was still really, really hard. There were many different ways to start, and I got some <a href="https://github.com/quarto-dev/quarto-cli/discussions/6975">excellent feedback</a> from people in the R / Quarto dev community. Garrick Aden-Buie in particular was the first to <a href="https://github.com/quarto-dev/quarto-cli/discussions/6975#discussioncomment-8828907">propose the idea of using fences</a> to denote page breaks, which was a big breakthrough early on.</p>
<p>But the biggest breakthrough came when I started using GPT-4 to help me brainstorm many different ideas while developing the overall platform architecture. <a href="https://chatgpt.com/share/57fda3b1-2e76-4ab1-b7af-e53eac597986">This conversation</a> in particular was game changing. In it, I came to solutions for multiple complex problems, including the page navigation logic and which platform to use for the database (we originally started with using Googlesheets, but ultimately decided on Supabase because it is open-source and just far easier to use).</p>
<p>Of course, the AI didn’t do everything. Two of my students, <a href="https://github.com/pingfan-hu">Pingfan Hu</a> and <a href="https://github.com/Buneabt">Bogdan Bunea</a> have been instrumental in helping implement many of the features the package now has, and they too have leveraged LLMs to accelerate their problem solving. Thank you guys for all of your hard work! 🙏</p>
<p>It’s been amazing watching this project come together over such a short period of time. The original conversations I had with GPT-4 and others in the R / Quarto community were just in March and April of this year (2024). We really didn’t start developing in earnest until the summer, and really only late June / early July at that. In just a few months, we’ve gone from an idea to a fully functional survey platform.</p>
<p>If you give surveydown a try, please let us know what you think! And if you find a bug or something you wished existed, please post an issue on <a href="https://github.com/surveydown-dev/surveydown/issues">github</a>.</p>
<p>I’m so excited to see what you all will build with surveydown!</p>


</section><a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>R</category>
  <category>package</category>
  <category>markdown</category>
  <category>shiny</category>
  <category>quarto</category>
  <guid>https://www.surveydown.org/blog/2024-08-21-introducing-surveydown/</guid>
  <pubDate>Wed, 21 Aug 2024 00:00:00 GMT</pubDate>
  <media:content url="https://www.surveydown.org/blog/2024-08-21-introducing-surveydown/banner.png" medium="image" type="image/png" height="96" width="144"/>
</item>
</channel>
</rss>
