# Candidate experience survey kit: method and field dictionary

All DEMO records are invented. Use the files without a Metix account. The Python 3 script reads a local CSV, validates it and writes a CSV to standard output. It makes no network request and writes no database. Your own exports and saved reports remain your responsibility.

## Files and command

Keep candidate-experience-survey.py and candidate-experience-example.csv in one folder. Run:

```sh
python3 candidate-experience-survey.py candidate-experience-example.csv --as-of 2026-11-01 > results.csv
```

Compare results.csv with candidate-experience-expected.csv. Copy the header from candidate-experience-batches-template.csv for your own data. Edit candidate-experience-questionnaire.md and use candidate-experience-actions.csv as a sample action log. The questionnaire and log are editable; the script does not send surveys or follow-ups.

## One row

One row is one question in one invitation batch. A batch contains invitations sent on the same calendar date under one rule, stage, recorded outcome and survey version. Use one documented timezone before assigning dates. Do not use this aggregate format to combine invitations sent on different days. Multiple questions may share a batch ID; their batch metadata must agree. The script produces no pooled total.

| Field | Definition |
|---|---|
| batch_id | Stable ID for a distribution batch; no names or contact details. |
| stage | Completed hiring step such as screen or interview. |
| outcome | A consistently recorded disposition such as not_progressed or accepted. Record when the disposition is assigned; do not mix at-send and final outcomes. |
| survey_version | Wording, response options, invitation rule and positive threshold version. Change it when those definitions change. |
| question_id | One item such as Q1; keep item wording traceable in your own questionnaire. |
| sent_on | Calendar date the invitations were actually sent. |
| window_days | Follow-up days after sent_on, 1-365. The example uses 7 as a method demonstration, not an optimal survey window. |
| counts_through | Inclusive final date included in the counts: the earlier of sent_on + window_days and the reporting cutoff. Freeze closed-batch counts at that endpoint. |
| invited | Distinct people invited in this batch. A reminder is not a new invitation. A zero is known zero, not missing data. |
| delivered | Distinct invitees with confirmed delivery under your stated delivery definition, or blank if unknown. Delivery does not mean read. |
| responses | Distinct invitees who submitted a survey by counts_through, after your documented duplicate handling. |
| answered | Distinct respondents with a valid substantive answer to this item. Exclude skipped, not applicable and prefer-not-to-answer options under the documented rule. Blank if unknown. |
| positive | Valid item answers in the positive category you defined in advance, or blank if unknown. Q1 v1 uses 4 or 5. |

ID and label fields use 1-64 letters, digits, underscores or hyphens, starting with a letter or digit. Keep the header order supplied. Counts are nonnegative integers. `answered` and `positive` must both be known or both blank. If zero people answered a tracked question, enter 0 and 0; the positive percentage remains undefined. Empty percentages mean unknown, undefined or withheld; read the status and input fields to distinguish them.

## Observation and denominators

For DEMO01, sent_on October 1 plus 7 days ends October 8, including that date. A November 1 report uses counts frozen through October 8. For DEMO06, the window ends November 4. Its observed counts run through November 1, but all three percentages are withheld until the full window closes, even though six people already responded positively. Later reports require the correctly refreshed endpoint counts; the script does not invent them.

For a closed batch:

- Response percentage of invited = responses / invited * 100.
- Response percentage of delivered = responses / delivered * 100, only if delivery is known.
- Positive item percentage = positive / answered * 100.

DEMO01 gives 6/20 = 30.0% of invitations, 6/18 = 33.3% of known deliveries, and 4/5 = 80.0% of valid Q1 answers. Four positive answers do not mean 80% of the 20 invitees were satisfied. One respondent skipped or selected a non-substantive Q1 option; 14 invitees did not submit a response by the endpoint. Their opinions are unknown.

DEMO04 shows a valid 3/12 = 25.0% invitation response rate while delivery and item percentages stay blank. DEMO05 shows known zero response, but no positive-answer percentage because nobody answered. A zero denominator produces a blank, not 0%.

## Checks and limits

The script rejects duplicate batch/question pairs, inconsistent metadata across questions in one batch, responses above invitations, invalid delivery counts, item counts outside responses, bad dates, stale or late count endpoints, future invitation batches and partially unknown item counts. It validates every row before emitting a report.

The script cannot inspect your survey platform, establish unique respondents, remove reminder duplicates, detect people appearing under several IDs or prove that counts exclude late answers. Prepare those counts in your authorized collection system. It cannot guarantee anonymity, validate a questionnaire, correct nonresponse bias, infer why someone withdrew or identify a cause of a rating. Aggregate data may still identify people in small groups.

Compare only like stages, outcome definitions, question wording, invitation rules, windows and privacy modes. Record changes instead of pooling versions. Inviting only people hired answers a question about that group, not everyone who interviewed. Avoid recruiter rankings from tiny or differently composed groups. Review sensitive comments through the appropriate internal process, keeping survey feedback out of selection scores.

Use a specific comment to open an investigation, name an action owner and set a review date. Verify whether the promised change happened. Treat the next comparable batch as further evidence, not proof that the change caused a score to move.
