Anticode Open builder

Site functions: run your own logic when someone sends a form

A site function attaches your own logic to a form on a published Anticode site. When a visitor sends the form, Anticode's server makes a signed HTTPS call to an endpoint you run (Google Apps Script, Zapier, Make, n8n or your own server) and writes its reply onto the thank-you page. Your code never runs inside Anticode, and the page itself still ships no scripts.

Updated · By the Anticode team

The wall it gets you past

Anticode's published pages run no JavaScript, and their forms post to fixed paths that Anticode validates and stores. That's a large part of why they're hard to break, but it leaves no room for rules that belong to your business: refuse a booking if the slot is already in your own spreadsheet, check a postcode against the areas you cover, reply with a reference number from your system. Site functions are the gap in the wall: custom server logic for website forms, placed where a visitor's browser can't tamper with it.

Setting one up

  1. Open the Console tab in the builder and choose Functions.
  2. Give the function a name (lowercase letters, numbers and dashes) and pick when it runs: the booking form, the contact form, the newsletter form, or a custom form.
  3. Under What it does, choose Call my endpoint and paste an HTTPS address. It's stored encrypted; afterwards only its host is shown.
  4. Choose what happens if it fails or times out (accept the form anyway, or refuse it) and a time limit of 2, 4 or 8 seconds.
  5. Copy the signing secret. It's shown once. New secret replaces it later if it leaks.
  6. Press Test. Anticode calls your endpoint with sample data marked as a test and shows exactly what a visitor would see, and whether the submission would be saved.

A custom form is how you collect fields the built-in forms don't have. It posts to /api/fn/<name> with up to 30 plain-text fields, and the Functions panel shows the form markup to start from. The other choice under What it does, Calculate from the form, runs a small formula on Anticode's server with nothing to host; it has its own page on formula functions.

What happens when a visitor sends the form

The usual form guards run first: the request must come from the site itself, rate limits apply, the body is capped at 16 KB and the fields are validated. A booking for a slot that's already taken is refused before your function is called. Then Anticode sends your endpoint a POST with JSON naming the function, the site, the form, the visitor's fields, a run id and whether it's a test.

The request carries an anticode-signature header in the form t=<unix seconds>,v1=<hex>, where the hex is an HMAC-SHA256 of the timestamp and the body using your signing secret. Your endpoint recomputes it to prove the call came from Anticode, and can reject calls whose timestamp is more than a few minutes old so a captured request can't be replayed.

The reply

Answer within the time limit with a 2xx status and JSON containing any of ok, title, message and lines (a list of label and value pairs). With ok true or left out, the submission is stored as usual and the thank-you page shows your title, message and lines in the site's own design. With ok false, nothing is stored and the visitor sees your title and message instead, such as "That time is taken. Please pick another slot." The reply is read through a strict schema (at most 12 lines, lengths capped, unknown keys dropped) and escaped, so markup in it arrives as plain text.

When the endpoint fails

A timeout, a network error, a status outside 2xx, too many redirects or a reply that doesn't fit the schema all count as a failure. Your endpoint's own words are never shown to visitors in that case, since they might be an error page or a stack trace. You decide what a failure means:

The two failure modes
SettingVisitor seesSubmission
Accept the form anyway (the default)The usual thank-you pageStored and sent to your inbox and connectors
Refuse the formA message asking them to try againNot stored

Accept suits optional extras, such as a reference number. Refuse suits checks that must pass, such as availability. The panel shows each function's last result and timing (Worked, Timed out, Couldn't be reached and so on); visitors never see those.

How it's kept safe

  • Anticode runs none of your code. It sends one signed request and parses a small reply.
  • Sealed secrets. The endpoint address, which often carries a token of its own, and the signing secret are encrypted at rest with AES-256-GCM.
  • Address checks. The URL must be HTTPS on the standard port and a public hostname, not a bare IP address and not Anticode itself; every DNS answer must be public. Up to two redirects are followed, each one re-checked, and the signature is never sent past the first hop.
  • Rate limits per function, 30 calls a minute and 1,000 an hour, so a flood of form posts can't become a flood against your server.
  • Plan limits. A project can have two functions on Free and twenty on paid plans, of either kind.

Limits

  • After submit only. The function runs when the form is sent. Nothing updates while the visitor types, because the page runs no scripts.
  • One function per built-in form. Each custom form has its own.
  • Plain text in and out. The reply is text and label-value lines, not a page of its own.
  • Apps Script and headers. Google Apps Script can't read request headers, so for it the usual approach is a secret in the endpoint's query string that your script compares.

If all you need is a copy of each submission in another tool, a form connector or a plain webhook is simpler. New to the idea? Start with what a webhook is.

Questions people ask

Can a site function stop a booking from being saved?

Yes. Reply with ok set to false and the booking isn't stored; the visitor sees your heading and message instead of the thank-you page.

What happens if my endpoint is slow?

After the time limit you chose, the call counts as failed, and the failure mode you picked decides whether the form is accepted or refused.

Can I test without a real visitor?

Yes. The Test button calls your endpoint with sample data marked as a test and shows the result as a visitor would see it.