Feedback via Google Apps Script
Feedback via Google Apps Script
Overview
Flow:
Android app -> HTTPS POST -> Google Apps Script Web App -> Google Sheets
The app sends a JSON payload directly to a deployed Apps Script Web App. The script validates the request, appends a row to a Google Sheet, and returns a small JSON response. The implementation stays intentionally small for this MVP, but it now includes stricter payload validation, a shared token, and a message length limit.
Google Sheet
Recommended spreadsheet name:
El Infiltrado Feedback
Recommended tab name:
Feedback
Exact columns and order:
createdAttypemessageemailappVersionlocaleplatformoptionalContext
Example row:
2026-03-14T18:42:10.000Z | suggestion | More category packs please | mail@example.com | 1.0.0 | es | android | {"clueRounds":2,"playerCount":6}
optionalContext is stored as JSON text and may include:
clueRoundsplayerCount
Apps Script
Use the script in feedback-apps-script.gs.
Before deploying, set:
SHEET_IDSHEET_NAMESHARED_TOKEN
Use a long random token and keep the same value in Android and Apps Script.
Deploy the Web App
- Create a Google Sheet and copy its ID from the URL.
- Open script.google.com and create a new Apps Script project.
- Paste the contents of
docs/feedback-apps-script.gsintoCode.gs. - Set
SHEET_IDto your spreadsheet ID. - Keep
SHEET_NAMEasFeedback, or change it in both places. - Set
SHARED_TOKENto the same long random string used in Android. - Deploy as
Web app. - Execute as:
Me. - Who has access:
AnyoneorAnyone with the link. - Copy the deployed
/execURL.
Configure the Android app
Set the endpoint through a Gradle property:
feedbackEndpointUrl=https://script.google.com/macros/s/YOUR_DEPLOYMENT_ID/exec
Set the shared token through another Gradle property:
feedbackSharedToken=YOUR_LONG_RANDOM_SHARED_TOKEN
Recommended place:
- user-level
~/.gradle/gradle.properties
On Windows, the equivalent user-level file is typically:
%USERPROFILE%\\.gradle\\gradle.properties
Alternative:
- project
gradle.propertiesif you intentionally want to share it with the team - a local machine-specific
gradle.propertiesthat is not committed
Recommended example in user-level gradle.properties:
feedbackEndpointUrl=https://script.google.com/macros/s/YOUR_DEPLOYMENT_ID/exec
feedbackSharedToken=REPLACE_WITH_A_LONG_RANDOM_SHARED_TOKEN
Do not hardcode either value in source files or commit real production values to the repository.
The data module exposes both values through:
BuildConfig.FEEDBACK_ENDPOINT_URLBuildConfig.FEEDBACK_SHARED_TOKEN
Payload sent by the app
typemessageemailtokenappVersionlocaleplatformcreatedAtoptionalContext
Validation enforced on both Android and Apps Script:
typemust besuggestionorproblemmessageis required and must be between8and1200charactersemailis optional, but must match a basic email format if presenttokenmust match the shared token configured on the serverplatformmust beandroidlocale,appVersion,createdAt, and optional context values must be well formed
The app does not send:
- game history
- secret word
- round logs
- device identifiers
The app may also send optional round context only when it is already available:
clueRoundsplayerCount
Known limitations
- The shared token is lightweight protection, not a full auth system.
- Apps Script quotas apply to requests and writes.
- Apps Script
ContentServicereturns JSON bodies, but does not provide robust custom HTTP status control in this setup. - In this phase there is no attachment support, no admin dashboard, and no server-side deduplication.
- If the endpoint URL or token is missing from the build config, the app shows a configuration error and does not send anything.