You've built a Google Apps Script that connects a Google Sheet catalogue to a simple order form, but when you try to publish it as a web app the button stays grey or users see a permission error. The symptom is clear – the app won't run for the intended audience – but the cause can be any of several setup gaps.
1. Quick answer: the essential deployment checklist
Before you click Deploy ► New deployment in the Apps Script editor, run through this short list:
- Confirm you have a single project file structure (Code.gs + any HTML files) and that the main function is named doGet(e) or doPost(e).
- Set the correct project version (create a new version for every public release).
- Choose the right execution access – either "Only myself" for internal tools or "Anyone, even anonymous" for public forms.
- Verify that every Google service your script uses (Sheets, Gmail, Drive, etc.) is listed in the OAuth scopes under Project Settings → Scopes.
- Test the web app URL in an incognito window to confirm the permission flow works for a fresh user.
- Record the deployment URL and version number in a central document for future updates.
If any step fails, the checklist points you to the exact place to troubleshoot.
2. Prerequisites – what you need before you start
2.1 Google account with editor rights
You must be logged into the Google account that owns the script project. Only the owner (or a user with Editor role) can create new versions and publish a web app.
2.2 A Google Sheet that will serve as the data source
Make sure the sheet is shared with the script owner at least with Viewer permission. If the script writes back to the sheet, grant Editor access.
2.3 Clear functional requirements
Write a one‑sentence description of what the web app should do (e.g., "Collect order details from a public form and write them to a Sheet"). This keeps the deployment scope narrow and avoids unnecessary scopes.
3. Step‑by‑step deployment plan
3.1 Organise your project files
- Code.gs – contains server‑side functions, including doGet(e) for GET requests and doPost(e) for form submissions.
- index.html – the main UI shown to users. You can have additional HTML files (e.g., thankyou.html) and include them with HtmlService.createTemplateFromFile().
- appsscript.json – automatically generated manifest that lists required OAuth scopes. Review it under View ► Show manifest file.
3.2 Define required OAuth scopes
When your script accesses a Google service, Apps Script adds a scope like https://www.googleapis.com/auth/spreadsheets. Too many scopes trigger a more aggressive security review and can scare users. Keep scopes to the minimum:
- Open appsscript.json.
- Remove any scope you do not need (e.g., delete Drive scopes if you never read/write files).
- Save the file – the editor will prompt you to re‑authorise the script.
3.3 Create a version
Every public release should be tied to a version number:
- Click File ► Manage versions.
- Enter a short description (e.g., "v1 – public order form").
- Click Save New Version. Note the version number (e.g., 1).
3.4 Deploy as a web app
- Choose Deploy ► New deployment.
- Select Web app as the deployment type.
- Set Execute the app as to "Me (owner)" if the script needs to write to the Sheet on behalf of the user.
- Set Who has access:
- "Only myself" – safe for internal tools.
- "Anyone" – public form, no sign‑in required.
- "Anyone with Google account" – useful when you need the user’s email.
- Choose the version you created in step 3.3.
- Click Deploy. Copy the generated URL.
3.5 Test the live URL
Open the URL in an incognito window (or a different browser profile). Verify:
- The UI loads without a "Authorization required" error.
- Form submissions create a new row in the Sheet.
- Any email notifications are sent (check the Gmail sent folder).
3.6 Set up logging and error handling
Even a simple app can fail when the Sheet reaches its row limit or when Gmail daily quotas are hit. Add these safety nets:
- Wrap critical code in try { … } catch (e) { Logger.log(e); MailApp.sendEmail(admin@example.com, 'Script error', e.stack); }.
- Open View ► Executions to see recent runs and any failures.
- Schedule a daily trigger (under Edit ► Current project's triggers**) that runs a small health‑check function and emails you if the last execution time exceeds a threshold.
4. Realistic example – a public order form for a small boutique
Scenario: A boutique in Karachi wants a simple web form where customers can request a custom t‑shirt size. The owner stores orders in a Google Sheet called Orders. The script must:
- Show a form (HTML) with fields: Name, Email, Size, Design reference.
- When submitted, append a row to the Sheet.
- Send a confirmation email to the customer.
Implementation highlights:
function doGet(e) { return HtmlService.createHtmlOutputFromFile('index'); } function doPost(e) { var ss = SpreadsheetApp.openById('YOUR_SHEET_ID'); var sheet = ss.getSheetByName('Orders'); var data = [ e.parameter.name, e.parameter.email, e.parameter.size, e.parameter.design, new Date() ]; sheet.appendRow(data); MailApp.sendEmail(e.parameter.email, 'Order received', 'We have your request.'); return HtmlService.createHtmlOutput('Thank you!'); }Following the checklist, the owner:
- Created the script in their own Google account.
- Limited scopes to spreadsheets and mail.
- Saved version 2 after adding the confirmation email.
- Deployed with "Execute as Me" and "Anyone" access.
- Tested the URL in a friend’s browser – the form worked, a row appeared in the Sheet, and the friend received the email.
If the friend had not received the email, the owner would check the execution log, see a "Daily quota exceeded" error, and decide to switch to a transactional email service.
5. Common mistakes and how to fix them
- Missing version number: Deploying without selecting a saved version defaults to the latest draft, which can change unexpectedly. Always create and select a version.
- Wrong execution access: Using "Only myself" for a public form blocks all external users. Change the access setting and re‑deploy.
- Over‑scoped permissions: Extra scopes trigger a security warning that discourages users. Review appsscript.json and remove unused scopes.
- Hard‑coded Sheet IDs: If the script is moved to another account, the ID may become inaccessible. Store IDs in PropertiesService.getScriptProperties() and document them for hand‑over.
- Ignoring execution logs: Errors are silent for end users. Regularly check View ► Executions or set up email alerts.
6. Deployment checklist – printable
- Project files organised: Code.gs, HTML files, appsscript.json.
- Functional requirement written in one sentence.
- OAuth scopes limited to only required services.
- Version created with descriptive label.
- Deployment settings:
- Execute as: Me (owner) or User (if needed).
- Who has access: Only myself / Anyone / Anyone with Google account.
- Live URL tested in a fresh browser session.
- Logging and error‑handling code added.
- Health‑check trigger scheduled (optional).
- Deployment URL and version recorded in a shared document.
- Backup of the script (File ► Export) stored securely.
7. Frequently asked questions
Do I need a paid Google Workspace account?
No. The free Gmail account can publish a web app, but quotas (e.g., email sends per day) are lower. If you expect higher volume, consider a Workspace subscription.
Can I change the web app URL after publishing?
The URL is tied to the deployment ID. Creating a new deployment generates a new URL; the old one remains active unless you delete the deployment.
What if I need to hand the project to another developer?
Transfer ownership of the Apps Script project (in the Google Drive file sharing settings) and update any stored IDs or API keys. Document the version number you consider "production".
8. Next steps
Now that you have a reliable deployment checklist, apply it to your own Apps Script project. If you run into permission errors, unexpected quotas, or need a more complex workflow (e.g., integrating a payment gateway), you can either extend the script yourself or request a focused review.
View the Apps Script ecommerce source‑code package for a ready‑made catalogue‑order example, or contact Nextpath Solutions with your goal, what you have tried, and the main blocker. We can help you identify the right next step.