You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(qualtrics): support dynamic reference params in Qualtrics element (#1217)
* feat(qualtrics): support dynamic reference params in Qualtrics element (#1211)
Qualtrics params now accept `reference` and `position` fields (same as
TrackedLink) so researchers can pass player state — urlParams, participantInfo,
prompt answers, etc. — directly into the survey URL at render time.
- Qualtrics.jsx: resolves reference params via referenceResolver (same logic
as TrackedLink); static `value` params continue to work unchanged
- validateTreatmentFile.ts: qualtrics params now validated with
trackedLinkParamSchema (key + optional value or reference + position)
- Added 6 Playwright component tests (QURL-001–006) covering static params,
always-present deliberationId/sampleId, urlParams reference, participantInfo
reference, mixed params, and QualtricsEOS submission
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(qualtrics): document reference params support (#1211)
Update qualtrics.md, page-elements.md, and syntax-reference.md to reflect
the new `reference`/`position` fields in params. Add examples for static,
dynamic, and mixed param configurations.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(qualtrics): move qualtricsSchema after trackedLinkParamSchema to fix TDZ error
qualtricsSchema referenced trackedLinkParamSchema before it was defined,
causing a ReferenceError at module load time that crashed batch creation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(qualtrics): rename params → urlParams to match TrackedLink API
Harmonize the Qualtrics element API with TrackedLink by renaming the
`params` field to `urlParams` across client, server validation, tests,
fixtures, and docs. Only the completed SDC_behavior study was using the
old name, so no active experiments are affected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(elements): extract shared URL param utils, fix warning + URL builder
- Extract serializeParamValue and pickFirstDefined into urlParamUtils.js
so Qualtrics and TrackedLink share one implementation (addresses Copilot
comment on duplication)
- Fix warning condition: fire only when pickedValue is undefined, not when
resolvedValue is "" (which is a valid empty-string param value)
- Build Qualtrics fullURL via new URL() + searchParams.append so existing
query params in the base URL are preserved and invalid URLs throw early
(addresses Copilot double-? comment and user's URL format check request)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
`Qualtrics: reference ${param.reference} resolved to undefined.`,
96
+
referenceValues
97
+
);
98
+
}
99
+
return{key: param.key,value: resolvedValue};
100
+
});
101
+
},[game,urlParams,player,players]);
70
102
71
-
constparamsObj=newURLSearchParams();
72
-
if(params){
73
-
for(const{ key, value }ofparams){
74
-
paramsObj.append(key,value);
75
-
}
76
-
}
77
-
paramsObj.append("deliberationId",deliberationId);// deliberationId is always passed so that we can link qualtrics responses to participants within qualtrics data
78
-
paramsObj.append("sampleId",sampleId);// sampleId is always passed so that we can link qualtrics responses to participants within qualtrics data
79
-
fullURL=`${url}?${paramsObj.toString()}`;
80
-
console.log("fullURL",fullURL);
103
+
constfullURL=useMemo(()=>{
104
+
consturlObj=newURL(url);
105
+
resolvedParams.forEach(({ key, value })=>urlObj.searchParams.append(key,value));
106
+
urlObj.searchParams.append("deliberationId",deliberationId);// always passed to link qualtrics responses to participants
107
+
urlObj.searchParams.append("sampleId",sampleId);// always passed to link qualtrics responses to participants
Copy file name to clipboardExpand all lines: docs/study-design/page-elements.md
+11-3Lines changed: 11 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -47,16 +47,24 @@ See [Prompt Files](prompts.md) for explanations of the various types of prompt a
47
47
48
48
## Qualtrics
49
49
50
-
This component embeds a Qualtrics survey inside an iframe in the current stage display. This is intended primarily as an escape hatch to allow study designers to use Qualtrics surveys to implement parts of the experiment that they Deliberation Lab does not yet support. Provide `url` and optional `params` (list of `{key, value}` objects). The component automatically appends `deliberationId` and `sampleId`, listens for the Qualtrics end-of-survey message, and records the session metadata. Completing the Qualtrics survey submits the stage, so no separate submit button is required.
50
+
This component embeds a Qualtrics survey inside an iframe in the current stage display. This is intended primarily as an escape hatch to allow study designers to use Qualtrics surveys to implement parts of the experiment that Deliberation Lab does not yet support. Provide `url` and optional `urlParams`. The component automatically appends `deliberationId` and `sampleId`, listens for the Qualtrics end-of-survey message, and records the session metadata. Completing the Qualtrics survey submits the stage, so no separate submit button is required.
51
51
52
-
In your qualtrics survey, make sure to either collect the deliberationId from the url parameter, or ask for participant's identifiers, so you can match data across platforms.
52
+
In your Qualtrics survey, make sure to either collect the `deliberationId` from the URL parameter, or ask for participant identifiers, so you can match data across platforms.
53
+
54
+
Optional `urlParams` let you append literal query parameters or reference values captured elsewhere in the study. Each parameter accepts:
- `reference`: optional [Reference Syntax](reference-syntax.md) pointer instead of `value` — resolved per-participant at render time. You can also pass `position` if you need a different subject (defaults to `player` when omitted).
- `url` is required; `params` is optional and is an array of key/value maps.
29
+
- `url` is required; `urlParams` is optional.
30
30
- At runtime, Deliberation Lab **automatically appends** `deliberationId` and `sampleId` as query parameters so you can join Qualtrics data to the science export even if API fetches are disabled.
31
31
- If `QUALTRICS_API_TOKEN` or `QUALTRICS_DATACENTER` is missing, batch initialization fails when validating treatments.
32
32
33
+
## Passing URL parameters
34
+
35
+
Each entry in `urlParams` accepts:
36
+
37
+
- `key`: required — the query parameter name.
38
+
- `value`: optional literal string, number, or boolean.
39
+
- `reference`: optional [Reference Syntax](reference-syntax.md) pointer resolved from player/game state at render time. Cannot be combined with `value`.
40
+
- `position`: optional position selector (`player`, `shared`, `all`, etc.) for the reference lookup — defaults to `player`.
41
+
42
+
**Static value** (same for all participants):
43
+
44
+
```yaml
45
+
urlParams:
46
+
- key: condition
47
+
value: treatment-A
48
+
```
49
+
50
+
**Dynamic reference** (resolved per-participant at render time):
51
+
52
+
```yaml
53
+
urlParams:
54
+
- key: prolificId
55
+
reference: urlParams.PROLIFIC_PID
56
+
- key: participantName
57
+
reference: participantInfo.name
58
+
```
59
+
60
+
**Mixed** (static and dynamic together):
61
+
62
+
```yaml
63
+
urlParams:
64
+
- key: condition
65
+
value: treatment-A
66
+
- key: prolificId
67
+
reference: urlParams.PROLIFIC_PID
68
+
- key: surveyAnswer
69
+
reference: prompt.topicChoice
70
+
```
71
+
72
+
Any reference namespace supported by the platform works here — `urlParams`, `participantInfo`, `connectionInfo`, `browserInfo`, `prompt`, `survey`, etc. See [Reference Syntax](reference-syntax.md) for the full list.
73
+
33
74
## What participants see
34
75
35
76
- The survey is embedded in an iframe sized for the stage.
- `prompt`: `type: prompt`, `file` required, `shared?` (true for shared prompt data; disallowed in intro/exit).
93
-
- `qualtrics`: `type: qualtrics`, `url` required (survey link), `params?` array of key/value maps. Runtime: env vars `QUALTRICS_API_TOKEN` and `QUALTRICS_DATACENTER` are required at validation time; Deliberation Lab appends `deliberationId` and `sampleId` to the URL automatically.
93
+
- `qualtrics`: `type: qualtrics`, `url` required (survey link), `urlParams?` array of param objects — each with `key` (required), and either `value` (literal string/number/boolean) or `reference` (reference string) plus optional `position`; `value` and `reference` are mutually exclusive. Runtime: env vars `QUALTRICS_API_TOKEN` and `QUALTRICS_DATACENTER` are required at validation time; Deliberation Lab appends `deliberationId` and `sampleId` to the URL automatically.
- **Template expansion** happens before validation is applied to the final structures used at runtime (`getTreatments` + `fillTemplates`). Unresolved `${...}` cause errors.
162
-
- **Qualtrics elements** require `QUALTRICS_API_TOKEN` and `QUALTRICS_DATACENTER` env vars; validation will throw if missing. At runtime, Deliberation Lab appends `deliberationId` and `sampleId` as URL params; submitted Qualtrics responses are fetched (if API keys) and stored under `qualtrics_<step>` in science data.
162
+
- **Qualtrics elements** require `QUALTRICS_API_TOKEN` and `QUALTRICS_DATACENTER` env vars; validation will throw if missing. At runtime, Deliberation Lab appends `deliberationId` and `sampleId` as URL params; any `urlParams` entries are also appended (with `reference` values resolved from player/game state); submitted Qualtrics responses are fetched (if API keys) and stored under `qualtrics_<step>` in science data.
163
163
- **Survey elements** rely on `@watts-lab/surveys`; ensure `surveyName` is valid there.
164
164
- **Discussion/video** layouts control Daily call composition; `rooms` split participants across subrooms; `layout` defines on-screen tiling for video stages.
165
165
- **Visibility/conditions** are evaluated in the client to gate rendering of prompts, displays, etc.; make sure referenced data exists in earlier steps or URL/browser/connection info.
0 commit comments