Have an idea?

Visit Sawtooth Software Feedback to share your ideas on how we can improve our products.

Zip Code validation

I have a list of 42,743 zip codes associated with all 50 US states.
We ask 2 questions. Q1. what is your state Q. What is your zip code?
I need to:
1. Validate the zip code entered in Q2 by a respondent is valid (part of that list)

2. Make sure there is a match between the state Q1 and zip code entered (If you tell me you are in NY, your zip code must be from the NY list.

3. Where there is a mismatch, an alert "Please enter a valid zip code for your state" should show up. The respondent should not be able to continue until there is a match.  If the mismatch persists after 2 attempts terminate.

4. Given the large number of zip codes, I need a way to do it that doesn't crash the survey.

I thought of using ranges, but there is a risk of letting invalid zip codes in. I know the valid zip codes, but not the invalid ones.

Can anybody share a code that can accomplish all this?
asked Sep 1, 2020 by rinsights Bronze (890 points)

1 Answer

0 votes
Alright, I think I've got this one figured out.  Let's start by creating an open-end question for the zip code and add a free format question to the same page.

The free format question should have a hidden, text variable named "_flag," and this code:

<input name="[% QuestionName() %]_flag" id="[% QuestionName() %]_flag" type="hidden" value=""/>

The free format should be given a skip that skips to your terminate page under these conditions:

Length(FreeFormatQ_flag) > 0

"FreeFormatQ" being the name of the free format question.

Now, let's go back to the open-end question.  We need to add this somewhere to the question (e.g., footer, HTML head):

<input id="zipErrorCount" type="hidden" value="0"/>

Finally, this is the custom JavaScript verification for the open-end:

[% Begin Unverified Perl
# Params
my $stateQ = 'SelectQ';
my $freeFormatQ = 'FreeFormatQ';
my %zipCodes = (
    1 => [123, 124, 125],
    2 => [234, 235, 236],
    3 => [345, 346, 347]
my $maxIncorrectZipCodes = 2;
my $errorMessage = 'Bad zip code.';

# Run
my $return = 'var zipCodes = {';
my @zips = @{$zipCodes{GETVALUE($stateQ)}};
my $sep = '';
foreach my $zip (@zips) {
    $return .= $sep . $zip . ':1';
    $sep = ',';
$return .= '};';
$return .= 'var freeFormatVariable = \'' . $freeFormatQ . '_flag\';';
$return .= 'var maxIncorrect = ' . $maxIncorrectZipCodes . ';';
$return .= 'var message = \'' . $errorMessage . '\';';
return $return;
End Unverified %]

var errorCount = Number($('#zipErrorCount').val());
if (!zipCodes[Number(SSI_GetValue('[% QuestionName() %]'))]) {
    if (errorCount > maxIncorrect) {
        $('#' + freeFormatVariable).val(1);
    else {
        strErrorMessage = message;

Lines 3 and 4 should be updated with the names of the state and free format question, respectively.  Lines 6-8 can be updated and repeated to represent the valid zip codes for each state.  Then lines 10 and 11 can optionally be updated if you want to change how many incorrect attempts respondents are allowed or what error message they are shown on an incorrect response.
answered Sep 2, 2020 by Zachary Platinum Sawtooth Software, Inc. (207,300 points)