This is a Google Apps Script for validating Google Forms responses using Cloudflare Turnstile. It requires the accompanying frontend to work. This project was created using the Google Forms Add-on Sample.
This add-on was designed for business Google Workspace accounts and may not work with a personal account.
This project requires Node 18.17.1 LTS or higher and a package manager such as NPM, yarn, or PNPM. PNPM is used in the npm scripts, which will need to be adjusted for your package manager.
NPM Script | Description |
---|---|
dev | launches a preview of the sidebar that automatically updates when the HTML is changed |
build | compiles the typescript into ./dist with the HTML |
clasp:push | Push the local changes to remote (don't forget to build first) |
clasp:deploy | pnpm build , clasp push , and clasp deploy in one |
This project requires Clasp, the Google Apps Script CLI. Please see the docs for installation details.
- Clone the repo
- Run
pnpm install
to install dependencies. NPM commands differ depending on your selected package manager. - Run
clasp login
to sign in to Clasp - Run
clasp create --title "Turnstile for Forms" --rootDir "./dist"
to create a new apps script project - Run
pnpm build
andclasp push
to build and push the files to remote
A Google Cloud project is needed to deploy and use the add-on. It may be usable through the editor add-on testing procedure, but I have not done it.
- Go to https://script.google.com/home , click on your project, and click on the settings icon on the left edge of the screen.
- In the project settings, scroll down until the "Google Cloud Platform (GCP) Project" section. Click "Change Project" and follow the instructions to create a GCP Project
- Deploy the add-on by running
clasp deploy
. Remember the deployment version number it returns. - Follow the Google Workspace Marketplace publishing documentation to publish the project as a private app.
- In the OAuth section, copy the scopes listed in
./public/appsscript.json
- In the store listing section, fill out the required details and the script version from step 3.
- In the OAuth section, copy the scopes listed in
- Once the app is published, install it to your account.
- Go to https://forms.google.com and create your forms.
- Token form
- Create a form with just two questions (case-sensitive): UUID (short answer), and Token (short answer). These will store the session UUID and Turnstile token.
- Create a linked spreadsheet for the form
- Open the spreadsheet and click the "Extensions" button on the top. Wait for the extension list to load.
- "Turnstile for Forms" will appear. Hover over it and click "Configure" to open the settings menu.
- Check "Enable Turnstile" and "Mark as Token Sheet"
- Enter your Cloudflare Turnstile secret key in the "Site secret" box and click "Save"
- Main form
- Create the form that you want to protect with turnstile.
- Create a question in the first section named "Secret" (case-sensitive) and optionally the following description
This is used to prevent spam and is automatically filled by Cloudflare Turnstile. Please don't touch or your submission will not be recorded. If this box is empty, please refresh the page.
- Create your other questions
- Create a linked spreadsheet for the form
- Open the spreadsheet and click the "Extensions" button on the top. Wait for the extension list to load.
- "Turnstile for Forms" will appear. Hover over it and click "Configure" to open the settings menu.
- Check "Enable Turnstile"
- Optionally check "Enable Notifications" and fill in the fields that appear to set up notifications
- Token form
- Set up the front end using the front end documentation
- Test the form by submitting a response
flowchart
A[User completes Turnstile challenge] --> B{Session ID + Token}
B --> C{Token Form}
C --> D{Token Sheet}
A --> E{User completes form}
E --> F{Form Response + \nSession ID}
F --> G{Form Sheet}
D --> H{Turnstile for Forms}
G --> H
H --> I{Cloudflare siteverify API}
I --> J{Success}
I --> K{Fail}
J --> L{Copy response to \nfiltered sheet}
J --> M{Send Discord notification}
K --> N{Highlight response red \nin sheet}