SheetLink Forms beta

Feedback and NPS into a living sheet

Scores and comments append to one sheet, and the NPS formula sits in a cell at the top. No survey subscription, no dashboard you check twice.

The workflow

NPS tooling has a funny economics: the input is one integer and an optional sentence, and the subscription costs more than the insight. The actual requirements are a form, a durable record, and one formula.

So: a feedback page (or an embedded form in your app) posts to a permanent endpoint, each response is screened and appended as a row, and the sheet holds your entire feedback history - scores in one column, comments in the next, timestamps in a third. The NPS number is a formula in a corner cell that updates as rows land. The delivery pipeline, retries included, is on how it works; you can watch a submission become a row on the live demo.

Suggested columns

Feedback sheets stay narrow:

  1. Score - the 0-10 integer. Keep it a bare number so formulas can chew on it.
  2. Comment - the sentence that explains the number, which is where the actual product feedback lives.
  3. Email - optional. Leave it optional in the form too; anonymous feedback is more honest and more plentiful.
  4. Context - a hidden input you set per placement (pricing-page, post-onboarding, cancellation), so one endpoint can serve several surfaces and still segment.
  5. Submitted At - for monthly cohorts.
  6. Followed Up - a working column for detractor outreach.

The form markup

A score dropdown, a comment box, the honeypot, and the embed so submitting shows an inline thanks instead of yanking the user to another page:

<form action="https://sheetlinkforms.com/f/your_token" method="POST" data-sheetlink
      data-success-message="Noted. Thank you.">
  <label>How likely are you to recommend us? (0-10)</label>
  <select name="score" required>
    <option>10</option><option>9</option><option>8</option><option>7</option>
    <option>6</option><option>5</option><option>4</option><option>3</option>
    <option>2</option><option>1</option><option>0</option>
  </select>
  <textarea name="comment" placeholder="What is the main reason for your score?"></textarea>
  <input type="hidden" name="context" value="post-onboarding">
  <input name="_slhp" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px">
  <button type="submit">Send</button>
</form>
<script src="https://sheetlinkforms.com/sl.js" data-token="your_token"></script>

Because sl.js binds forms via MutationObserver, this works inside a React or Vue app where the form renders after load - no extra wiring for SPAs. Embed attributes and the JSON API are in the docs.

Working the sheet

The whole analytics layer is three formulas and a filter:

  1. The NPS cell. With scores in column A: =ROUND((COUNTIF(A2:A,">=9") - COUNTIF(A2:A,"<=6")) / COUNT(A2:A) * 100). Promoters minus detractors, as a percentage, live.
  2. Monthly cohorts. The same formula wrapped over month-filtered ranges shows trend - the only NPS chart anyone actually uses.
  3. The detractor view. Filter: Score <= 6, Email present, Followed Up empty. That view is your outreach queue; write the date in Followed Up as you go.
  4. Read the comments column weekly. The number is for the board deck; the Comment column is for the roadmap.

Spam considerations

Feedback forms are low-value targets and get correspondingly little spam, so run the strictness dial at loose - the worst outcome here is a real, terse response ("3" and the comment "slow") getting held as a suspected empty payload. The honeypot still catches the crude bots, and per-IP rate limits stop one aggrieved user from submitting forty times.

Whatever does get flagged is quarantined for one-click review, never dropped, which fits feedback especially well: an angry detractor comment full of links looks spammy to a heuristic and is precisely the response you most need to see. Sweep the quarantine when you do your weekly comment read.

FAQ

Can feedback be anonymous?

Yes - the row contains exactly the fields you send. Leave Email optional (or omit the field entirely) and the sheet simply has blank cells there. Anonymous forms reliably collect more honest detractor feedback.

How do I compute NPS in the sheet?

One cell: =ROUND((COUNTIF(A2:A,">=9") - COUNTIF(A2:A,"<=6")) / COUNT(A2:A) * 100) with scores in column A. Promoters are 9-10, detractors 0-6, and the result updates as rows append.

Does the embedded form work inside a single-page app?

Yes. sl.js watches the DOM with a MutationObserver and binds forms whenever they appear, so a feedback modal that renders on click in React or Vue submits over AJAX like any other bound form.

Can one endpoint serve feedback forms in several places?

Yes - reuse the endpoint and vary a hidden context input per placement. The Context column then lets you segment scores by surface, which is usually more informative than the overall number.

Related: A contact form that lands in a sheet · Newsletter signups you own · Forms for side projects and hackathons

Request an invite See the live demo