GET and POST requests. Combined with backend scripts, this lets you build data-collection endpoints, custom forms, and mini-apps using regular ElasticFunnels pages — no external server needed.
The pattern
- Create a page (e.g.
/weight/checkin) - Add a
<script scope="backend">that checks forPOST, validatesrequest.bodywith the Schema validator, and stores the data - Your frontend uses
fetch()to POST JSON data to that page - The backend script responds with JSON — the page HTML is skipped when
response.json()is called
Full example: Weight check-in
1. Create a shared validation module
Create a backend script module (code:validators) with shared schemas:
2. Create the page /weight/checkin
3. Read the data back on another page
On any page (e.g./dashboard), read the CRM data:
How it fits together
CRM functions reference
Where a new entry lands. An entry created by
setCrmField / setCrmFields is stored on no pipeline and no stage (pipeline and stage 0), not on the entity’s first pipeline and not on the “Form Submissions” pipeline that a plain collection form post uses. If your team works the entries from a pipeline board, follow the write with moveCrmToPipeline({ slug, pipelineSlug, stageSlug, ... }) (same reference arguments).slug (CRM entity) vs reference
slug — required on every call. This is the CRM entity slug from entity settings (e.g. pattern-tracker). It is not the same as referenceType (customer, order, …).
referenceType / referenceId — which record entries attach to. Omit or null for 'customer' and the session customer_id.
Parameter types
Moving through CRM workflow
moveCrmToStage and moveCrmToPipeline are the workflow transition functions. You can move:
- Stage to stage in the same pipeline
- Pipeline to pipeline (by setting a stage that belongs to the new pipeline)
pipeline_id, stage_id). They do not map one field key into another.
For field mapping (for example quiz_email -> email), do it explicitly with reads/writes:
Input validation
All inputs are strictly validated before data is stored:slugmust match a CRM entity configured for your brand; unknown slug →TypeErrorfieldKeymust match/^[a-zA-Z0-9_.-]+$/referenceTypemust match/^[a-zA-Z0-9_-]+$/referenceIdrejects{}[]"\characters- String values are capped at 10,000 characters
- Numbers must be finite (no
NaN,Infinity) - Objects are JSON-serialized and capped at 10 KB
- Missing
slug,fieldKey, orvalue(set) throwsTypeError - Other invalid inputs still cause
false/null/[]where applicable
Quiz / anonymous visitor → customer CRM migration
A common pattern: save a quiz or funnel payload withsetCrmField({ referenceType: 'quiz_visitor', referenceId: sessionUuid, ... }) while the visitor is anonymous, then after members login call reassignCrmReference so the same CRM entries attach to customer + customer_id. fromReferenceId must match session.get('quiz_visitor_id') and the target must be the current session customer — see ReassignCrmReference on the Data Functions page. Clear quiz_visitor_id from the session after a successful migration to keep the flow idempotent.
Security checklist
- Validate with Schema — use the built-in Schema validator to enforce types, lengths, and allowed values
- Check authentication — verify
is_customerbefore storing data - Use
response.json()— this stops page rendering and returns JSON directly - Use
response.status()— set proper HTTP status codes (400 for validation errors, 401 for auth) - Share validation logic — create a backend script module for reusable schemas and auth checks
POST body limits
Related
- Backend Scripts Overview — how backend scripts work, sandboxing, execution order
- Schema Validator — full reference for the
Schemavalidation API - Shared Modules — import/export reusable code between pages
- Request Context —
request.body,request.method, and other globals - CRM Overview — entities, fields, pipelines, and the CRM data model