CoeveraBlueprints

Blueprint 012 · Feedback

How do you run a customer survey from your CRM and get the answers back onto the record?

Native online forms, the three ways a response attaches to a record, and why the built-in response rate reads over 100%.

Revised 2026-09-10Grounded in a 74-form production estateMarkdown twin ↓

The short answer

Coevera has a native online forms subsystem, and the survey is a form. The form definition names exactly one entity type it can attach to. A submission creates a response record holding the answers, and the form's own settings decide what happens next: link the response to the surveyed record, write the answers onto it, or create a new record.

Form submission is one of only four process trigger types — alongside record change, schedule and manual — so a survey is a first-class automation event rather than something you detect after the fact.

The caveat is the metric. The built-in response rate is responses ÷ unique recipients, so it is blank for any form you published rather than emailed, and reads over 100% as soon as one recipient answers twice.

01The business problem

There are moments when a customer will tell you something useful: just after a renewal, just after a meeting, a few weeks after going live, at the point a relationship is being reviewed. Asking is the easy half. The hard half is that the answer has to arrive where the person who acts on it already works.

A satisfaction score in a spreadsheet is not an intervention. The manager who owns the relationship opens the customer record, and if the record says nothing about the survey, the survey did not happen. So the requirement is not "run a survey" — it is:

  • ask at a moment triggered by something in the CRM,
  • have every answer attributable to a specific customer, deal or contact,
  • have the answers land on that record as values a report and a filter can see,
  • alert the right person when a particular answer arrives,
  • and know who was asked and has not replied.

That last one is the requirement people forget, and it is the one that decides whether the exercise produces a follow-up list or a vanity number.

02Why the obvious approach fails

A survey tool plus an integration

The default reach is a dedicated survey product with a CRM connector. It fails on attribution. The connector matches responses to records on an email address, and an email address is exactly the thing that does not survive a real send: the recipient forwards the invitation to a colleague, answers from a personal address, or is one of four people at the same company. What arrives is a response the CRM cannot place, and the usual outcome is a silently unmatched response — or worse, one matched to the nearest wrong record.

Building the questions as fields and mailing an edit link

The next idea is to put the questions on the customer record as fields and send the customer a link to edit them. There is no such link. Record forms are internal; they exist behind authentication and role permissions, and no configuration exposes one to an unauthenticated respondent.

Detecting a submission by watching a field

The received wisdom is to add a "terms accepted" or "survey completed" checkbox, make it mandatory on the form, and hang a change-triggered process off it. This works, and it is genuinely the pattern to use when a survey arrives from outside the platform. It is the wrong default here, for three reasons:

  • It fires on the wrong record. A change-triggered process on the account sees the account. It cannot see which form was answered or what the answers were, because those live on a separate response record.
  • A second submission may not fire it. The sentinel field is already true. A repeat response changes nothing, so nothing runs.
  • It is unnecessary. Form submission is a native trigger type. The sentinel is a workaround for a gap that is not there.

One form for the whole customer journey

The last mistake is structural rather than mechanical: assuming one questionnaire can follow a customer across the journey. A form definition names one entity type. A pre-meeting questionnaire that must attach to a lead before conversion and an opportunity after it is two form definitions, not one form with a switch.

03Data model

Three entities carry a survey, and the first thing to get straight is which one is which, because the names are misleading.

EntityWhat it actually isKey properties
Online form type The form definition — the survey you designed name, entityType (one only), the layout, a required styleId, a public link and linkId, isEnabled, hasDraft, and the counters sentCount, sentUniqueCount, responseCount, responseRate, lastResponseDate
Online form A single submitted response. Not the form. answers, respondedBy, responseDate, onlineFormTypeId, its own customFields, and primaryAccount / primaryContact / primaryLead / primaryOpportunity / primaryQuote / primaryCustomEntity
Online form relation The join from one response to the records it concerns accountId, contactId, leadOpptyId, quoteId, projectId, customEntityId, plus isPrimary

Naming trap. The entity called online form is a response, and the entity called online form type is the form. Everything reads correctly once you translate "type" as "definition" and "form" as "submission".

What a response can attach to

The relation join carries account, contact, lead, opportunity, quote, project and custom entity, with one of them flagged primary. So a single response can sit on the account and the deal it was asked about, and the primary flag is what a report groups by.

A custom entity is admitted by both the entity-type enum and the relation. That is schema-verified but not behaviour-verified — no live example of a custom-entity-bound form was available to read. It matters because it is the opposite of the approval subsystem, which cannot target a custom entity at all; see Blueprint 001.

The answers themselves

An answer is a pair: the id of the form field, and a string value. There is no typing in the response. A rating of 4 arrives as text, a multi-select arrives as text, a date arrives as text. Everything you intend to filter, average or chart has to be written out to a typed field on a record — which is what §04 and §05 are for.

Who was asked, and who answered

Responses roll up per form into four categories, and they are the reporting surface that matters more than the response count:

CategoryWhat it gives you
SentEvery record the form was sent to
RespondedRecords that answered — records, not responses
SentAndNotRespondedThe chase list. This is the one that makes a survey operational
UnknownRespondentsResponses that arrived but matched no record

The alternative that was rejected

Modelling a survey response as a custom entity is the reflex when a platform's native subsystem looks thin. Here it costs more than it gives: you would rebuild the public URL, the send tracking, the four roll-up categories, the unknown-respondent bucket, the response PDF and the submission trigger, and you would still have no form renderer. The decision framework for that judgement is Blueprint 003. A custom entity is the right answer when what you need is a reviewable record with its own lifecycle and owner — which a response is not. The response record does take custom fields of its own, so a derived score can live on the response without a new entity.

04Field-level configuration

The field types available on a form

Fifteen, and the absences matter as much as the presences:

GroupTypes
Textsingle-line input, text area, email, phone
Numericinteger, float, rating
Choicedropdown, radio, multi-select checkbox, single checkbox
Temporaldate, date-time
Otherfile upload, products & services
Absentno lookup field, no currency field

The products-and-services field is worth knowing about on a survey rather than an order form: it turns "are you interested in additional services?" into a priced selection against a named price list, so an expression of interest arrives already quantified. Pricing behaviour is in Blueprint 007.

What every form field carries

PropertyPurpose
fieldIdThe CRM field this question maps to
required, visible, readOnlyStandard; visible: false is load-bearing — see below
prefillEnabled, prefillTypeField draws from a record field, Custom uses a fixed value
prefillFieldId, prefillLookupFieldIdWhich record field, optionally across a lookup
conditionalRulesFilterA normal field filter — this is how a question appears only when an earlier answer warrants it
nameThe question label, and it is HTML. Paste from a document and the pasted colours travel with it

Rating fields

A rating field is bounded by valueFrom and valueTo with valueFromLabel and valueToLabel as anchors. A net-promoter question is 010 labelled Most unlikely / Most likely; a satisfaction question is 15; a traffic-light is 13. Same field type, three surveys. Pick the bounds once — changing them later invalidates comparison with every response already collected, and nothing warns you.

How the response finds its record — the central decision

Three settings on the form, and choosing between them is the whole design:

SituationSettingHow identity arrives
Sent to a known person about a known record linkRecordEnabled From the send itself. No answer is needed to establish identity, and autolink stays off
Published on a page or embedded in an email autolinkEnabled + autolinkFormFieldId + autolinkRecordFieldId One form field is matched against one record field
The respondent is not in the CRM yet createRecordEnabled A new record is created from the answers

The elegant part is how prefill and autolink combine. Put an email field on the form, prefill it from the record's email field, and set autolink to match that same form field against that same record field. Sent from the record, it arrives pre-filled and attaches instantly. Reached cold from a published link, the respondent types their address and it attaches anyway. One configuration, both paths.

Alongside it, carry the identity you actually trust in hidden prefilled fields: visible: false, prefillEnabled: true, pointed at the account name and the account identifier. They never render, they travel in the link, and they give the response an identity that does not depend on what the respondent typed.

Writing answers onto the surveyed record

With updateRecordEnabled, the form carries an update template — an ordinary record template whose values are ppl-tag references to form fields:

{"customFields": {
  "cfLikelyToRecommend":
    "<ppl-tag data-id=\"{rating-form-field-id}\" data-relation-type=\"Responses\"></ppl-tag>",
  "cfSurveyDateFilled":
    "<ppl-tag data-id=\"CurrentDate\"></ppl-tag>",
  "cfSurveyRespondent":
    "<ppl-tag data-id=\"{first-name-field-id}\" data-relation-type=\"Responses\"></ppl-tag> <ppl-tag data-id=\"{last-name-field-id}\" data-relation-type=\"Responses\"></ppl-tag>",
  "cfSurveysCompleted": ["{option-uuid}"]
}}
  • data-relation-type="Responses" is what pulls the value from the submission.
  • CurrentDate is a built-in tag — stamp the submission date here, not in a process.
  • Two tags in one target value concatenate, which is how first and last name become one field.
  • A dropdown or multi-select target is set by option UUID, never by label.
  • Every key in the template is part of the write. Keep it to the fields you intend to change: a key carrying an empty value is still in the payload. Whether an empty value clears the target field or is skipped was not tested.

The rest of the settings worth setting deliberately

SettingWhy it matters for a survey
limitToSingleResponse, checkForExistingResponse Both default off. Leaving them off is what lets one recipient answer repeatedly — and what breaks the response rate (§06)
notificationRecipientType Owner | PrimaryRecordOwner | Custom. PrimaryRecordOwner mails the owner of the record the response attached to — the relationship manager. A bare alert needs no process at all
attachResponseAsPdf Files the completed questionnaire on the record as a document. This is what makes the survey auditable a year later
responseAcceptanceDateLimitEnabled + date Closes the survey on a date with your own title and message, instead of collecting stragglers into a period you already reported
responseAcceptanceThresholdType TotalResponses | CustomCondition | ProductsLimits — capacity limits, for a survey that doubles as a registration
recordIdentificationEnabled Asks the respondent to identify their own record when autolink cannot
confirmationPageType ConfirmationPage | ExternalUrl
attachFiles, maxTotalUploadedFilesSize Needed if any question invites an attachment

05Automation & logic

Submission is a trigger type

The platform has exactly four process trigger types: record change, schedule, manual, and online form submission. A survey response is therefore a first-class event, not something inferred from a field that moved.

The trigger names three things, and the first one surprises people:

PropertyValueConsequence
entityType the response The process runs on the response record, not on the customer. Its filters read answers
recordType account, opportunity, lead, … What the response attached to, so actions can reach the customer record through the relation
onlineForms a list of form ids One process can serve many forms — a family of sibling questionnaires shares one automation

That list is the useful part. Where a survey is fanned out as several near-identical forms — one per department, one per audience — the whole set can hang off a single process rather than one process per form.

One form, several processes

The reverse is also true, and it is not a smell. A process carries exactly one filter at its root, and that filter's branches are first-match-wins. So four independent things to do with one submission — acknowledge it, route the rating, open a task if a meeting was requested, notify a product owner if a feature was named — are four processes, because any one of them can be true at the same time as the others. This is the same constraint that decides process counts everywhere else in the platform; Blueprint 011 covers it and the naming discipline that keeps such a family legible.

The rating router

The pattern that earns its keep: filter on the rating band, and send a different message per band. A low score mails the relationship owner immediately; a high score mails whoever collects references. Both are branches of one filter, because a response has exactly one rating — this is a genuine set of alternatives, so one process is correct.

Turning answers into structure

Two routes, with very different costs:

RouteCostUse when
The form's own update template (§04) Declarative, one write, no process The answers belong on the surveyed record as its current state — latest score, date last surveyed, latest verbatim
A process creating a related record per answer One node per answer. A twenty-question survey is a twenty-node process, and it grows every time a question is added Each answer must be its own reviewable row with a history — where the second survey must not overwrite the first

Reach for the template first. The related-record route is the right answer when history matters, but it is the expensive one and it is where survey automation becomes unmaintainable fastest.

Sending the thing

A form has a public link, so sending is an ordinary email action carrying that link with the prefill parameters. The consequence is that the send is the identity: a process that mails the link from the record is also what puts that record in the Sent category, which is what makes SentAndNotResponded — the chase list — exist at all. A survey published on a web page has no chase list, by construction.

06Limits & trade-offs

The built-in response rate is responses ÷ unique recipients. It is not a response rate in the sense anyone means it. It is blank for every form that was never emailed, and it exceeds 100% as soon as one recipient submits twice — which nothing prevents, because limitToSingleResponse is off by default.

In a production estate of 74 form definitions with three years of history, the arithmetic held exactly on all 30 forms reporting a rate, and:

  • 10 of those 30 reported over 100%.
  • 44 forms reported no rate at all — 21 of which were holding 491 responses between them. A form that is published rather than sent has a divisor of zero, so it has no rate, however many people answered.

Treat the figure as meaningful only for a form that is sent rather than published and limits each recipient to one response. Otherwise compute your own rate from the Sent and Responded categories, and be aware that Responded counts records, not responses.

Other limits, in the order they bite

  • A form belongs to one entity type. A questionnaire that must attach to a lead before conversion and an opportunity after it is two definitions, two answer mappings, and either two processes or one process naming both forms. There is no inheritance between them: a question added to one is not added to the other.
  • A public form with autolink and record-update both enabled is a write endpoint. Anyone who supplies a value matching the autolink record field writes to that record. If the matching field is an email address, the form is only as safe as the guessability of your customers' email addresses. Keep public forms to createRecordEnabled and reconcile, or autolink on a value that only the intended recipient could hold.
  • Unmatched responses are preserved, but nothing works them. They land in UnknownRespondents — which is much better than being discarded or misattached, and on one live embedded survey held 10 of 39 responses. But it is a bucket, not a queue: no owner, no task, no ageing. Give it a human and a cadence, or it becomes a place where customer feedback goes to be counted and not read.
  • Answers are strings. Nothing about a response is typed or aggregatable in place. Anything to be charted, averaged or filtered has to be written to a typed field by the template or a process — which means a question nobody mapped is a question nobody can report on, even though the answer is stored.
  • A response outlives the record it points at. Both the response and the per-record summary carry an availability flag, so a deleted or inaccessible record leaves responses pointing at nothing. Survey history is not a reason to keep a record, and deleting a record does not clean up its responses.
  • The platform's summarised response value cannot be relied on. The field exists on both the form and the per-record summary, and it was null on every one of the 74 forms examined. Compute the score you care about into a field of your own; do not build a report on that property.
  • Disabling a form retains its responses. Eleven disabled forms in the estate still held responses. Disabling is therefore safe as an archival step — but it is not a delete, and the responses stay attached to their records and visible in reports.
  • Rating bounds are not versioned. Changing valueFrom or valueTo silently makes new responses incomparable with old ones. Nothing marks the discontinuity.

The trade-off worth stating plainly

Native forms buy attribution, a submission trigger, a chase list and an answer-to-field mapping that needs no code. What they do not buy is a survey platform: there is no panel management, no reminder scheduling of their own, no cross-form benchmarking, and no statistical analysis. If the requirement is a research instrument, this is the wrong tool. If the requirement is that the account record knows what the customer said and someone gets told — which is nearly always the actual requirement — it is the right one, and it is the only option where the answer lands on the record without an integration in between.

07Verification

Read from a live production space on 2026-09-10: 74 form definitions accumulated over three years, their settings, their field-level configuration, their response roll-ups, and the processes triggered by them.

  • The response-rate formula was checked arithmetically against every form reporting one — 30 forms, zero mismatches with responses ÷ unique recipients × 100. The 44 forms reporting no rate all had zero recorded sends.
  • The four roll-up categories were read per form, and one embedded survey is what pinned the arithmetic down: 170 sent, 155 sent-and-not-responded, 23 responded, 10 unknown respondents, against a response count of 39. Responded plus unknown does not equal the response count because Responded counts records; sent minus not-responded does not equal responded because eight respondents were never sent it and arrived through the embed.
  • Two contrasting live configurations were read in full. An embedded survey with autolinkEnabled and updateRecordEnabled on and linkRecordEnabled off; and a sent fan-out with linkRecordEnabled on and both of the others off — identity from the send in one case, from an answer in the other.
  • The update template was read verbatim from a live form, which is where the ppl-tag shape, the Responses relation type, the CurrentDate tag, tag concatenation into a single target and option-UUID dropdown targets all come from.
  • Form-triggered automation was counted: 32 processes in the space use the online-form trigger, every one of them with the response as its trigger entity. One is bound to six sibling forms at once; one form is served by four separate processes.
  • Conditional question visibility was confirmed in use — a products-and-services question on a live survey carries a field filter and appears only when an earlier answer warrants it.

Not observed, and stated as such:

  • The public submission path itself — every finding here is read from stored configuration and stored results, not from a submission made for the purpose.
  • A populated summarised response value. It was null everywhere it appears.
  • A custom-entity-bound form. Schema-verified but not behaviour-verified.
  • Whether an empty value in the update template clears the target field or is skipped.
  • Whether a disabled form's public link rejects new submissions, as distinct from retaining the old ones — which was verified.

What would signal a regression

  • A send-only form's rate dropping below the number of responses you can see means sends have stopped being recorded, which silently destroys the chase list.
  • A rising unknown-respondent count is the single most useful alarm here: it means the identity path — prefill, autolink, or the send itself — has broken, and it will show up as "the survey is working fine" on every other measure.
  • A response count rising while the mapped fields on records stay stale means the update template stopped applying. Check the record, never the submission confirmation.
Published by Coevera · abstracted to the pattern, no client dataBlueprint 012 · rev 2026-09-10