Skip to main content

How to build an approval audit trail and compliance dashboard in Formaloo

Learn how to build an approval audit trail and compliance dashboard in Formaloo, with decision logic, an auto-generated PDF record, and a searchable dashboard.


What you'll build

By the end of this guide, you'll have a request-to-decision workflow that works for any approval, a policy exception, a contract sign-off, a data access request. Every request captures the evidence up front, routes to a reviewer, and the moment a decision is recorded, Formaloo generates a signed audit PDF and notifies both the compliance inbox and the requester. A compliance dashboard rolls every decision into a searchable table, a reviewer pipeline, and a chart tracking approval versus rejection rates over time.

💡 Want a request to move through review, approval, or rejection stages automatically? This is the complete, foundational guide to approval workflows, status fields, admin-only dropdowns, and logic-based routing together. See how to build an approval workflow in Formaloo.

When to use this

  • Compliance or legal keeps getting asked "who approved this, and why" for a decision made months ago, and there's no single place to point to

  • You're running approvals over email or Slack and have no consistent record of the rationale behind a decision

  • An audit or regulator asks for proof of your review process, and pulling it together means digging through old threads

  • You need reviewers and compliance leadership to see different views of the same request pool, without giving everyone full access

  • You want a trend line on approval versus rejection rates instead of manually counting rows in a spreadsheet

Part 1 — Build the request and decision form

This is where everything starts. You'll build a single form that captures the request itself and, in the same place, a private decision section only your reviewers can see. Keeping both in one form means one submission and one PDF instead of stitching records together after the fact.

1. Open Magic Create: From your Formaloo homepage, click Magic Create, then describe the form: a compliance request form collecting the requester's full name, work email, department, a one-line request summary, a detailed description, and a file upload for supporting documentation, plus a yes/no confirmation that the information is accurate. Also describe the admin-only section: a Status dropdown (Pending review, Approved, Rejected), an Assignee field, a reviewer's typed name field, a decision rationale long text field, a decision date field, and internal notes. Click Create.

2. Verify your fields: Your form should look like this, Magic Create will have generated most of it. Verify each field and field ID matches exactly.

Field (question form)

Field ID

Type

What's your full name?

requester_name

Short text

What's your work email address?

requester_email

Email

Which department or team is this request for?

department

Dropdown

What are you requesting approval for?

request_summary

Short text

Describe the request in detail

request_details

Long text

Upload any supporting documentation

supporting_docs

File upload

Do you confirm the information above is accurate and complete?

accuracy_confirmation

Yes/No

Status

status

Dropdown (admin-only)

Assignee

assignee

Assignee field (admin-only)

Reviewer's typed name

reviewer_name

Short text (admin-only)

Decision rationale

decision_rationale

Long text (admin-only)

Decision date

decision_date

Date (admin-only)

Internal notes

internal_notes

Long text (admin-only)

💡 Want internal fields, status, assignee, scores, invisible to the person filling out the form? Admin-only fields are the mechanism. See what admin-only fields are and how they help.

3. Add the warning statement: Add one more field manually, a static text field with the message "Please double-check your details before submitting, this record becomes part of a compliance audit trail." Give it the field ID accuracy_warning and hide it by default. You'll wire up the rule that reveals it in Part 2.

4. Mark the decision fields as required: Open Reviewer's typed name, Decision rationale, and Decision date, and turn on Required for each. This keeps a reviewer from changing Status to Approved or Rejected while the audit record is still incomplete.

💡 Want to know exactly what the Assignee field can do, assign to a person, a team, or either? This is the atomic reference for that field type. See what is the Assignee field in Formaloo and how to use it.

5. Publish the form: Click Publish in the island bar at the top of the editor.

Part 2 — Add the accuracy gate

Before you touch email or PDF automation, wire up the one piece of logic that lives entirely on the form: the warning that appears if a requester says their information isn't accurate.

💡 Want your form to show, hide, skip, or require fields based on what someone just answered? This is the foundational guide to logic in Formaloo, what it is, and the difference between logic and calculation. See what is logic in Formaloo.

1. Open Advanced logic: In the form settings panel on the right side of the form editor, open Advanced logic, then go to the Logic tab.

2. Use Magic Logic: Click Magic Logic in the top right corner of the Logic panel, then paste: "If 'Do you confirm the information above is accurate and complete?' equals No, show the statement 'Please double-check your details before submitting, this record becomes part of a compliance audit trail.' Keep it hidden by default." Click Generate rules.

3. Approve the rule: Review the AI-generated rule preview, then approve it. Make manual adjustments if anything needs fixing.

4. Save: Click Save in the top right corner.

Part 3 — Set up your notification emails

With the form live, build the two straightforward emails that fire the moment a request comes in: a confirmation to the requester and an alert to whoever it's assigned to.

💡 Want to send branded, personalized emails instead of Formaloo's plain default notification? This is the foundational guide to building and sending custom email templates. See how to create and send custom email templates.

1. Create the submission confirmation template: In your project, open Email templates and create a new template named "Submission confirmation." Use the AI Email Assistant to generate the body from a prompt, rather than typing static copy, so paste in the full template below.

Submission confirmation Subject: We've received your request, @request_summary Body prompt: Write a warm, professional confirmation email to the requester letting them know their approval request has been received and is now in review. Reference the request summary (@request_summary) and the department it was submitted for (@department). Reassure them the request is being tracked as part of a compliance audit trail and they'll be notified as soon as a decision is made. Keep the tone calm and factual, not casual. 3-4 sentences. HTML design: white background, single centered column, max-width 560px, Inter/system-ui font, a small "Pending review" status badge near the top, muted footer in #999 with the org name placeholder. Trigger: When the requester submits the form, immediately send this email to @requester_email.

💡 Want to pull a submitter's own answers into later questions, emails, or PDFs? Answer piping is how Formaloo passes data using @field_id variables. See how to use answer piping in Formaloo.

2. Create the reviewer notification template: Create a second template named "New request assigned," again using the full template below.

New request assigned Subject: New request assigned to you, @request_summary Body prompt: Write a brief, task-oriented email to the internal reviewer letting them know a new request has been assigned to them. Include the requester's name (@requester_name), department (@department), and request summary (@request_summary). Prompt them to open the request and record a decision. 2-3 sentences, no filler. HTML design: white background, max-width 560px, Inter font, a compact two-row data table showing Requester / Department / Request, a clear "Review this request" link styled like a button, muted footer #999. Trigger: When the requester submits the form, immediately send this email to the reviewer assigned via the Assignee field's recipient option.

Part 4 — Build the PDF audit record template

This is the document that makes the workflow defensible: a signed, permanent record generated the instant a decision is made.

💡 Want every form submission to generate a polished, branded document automatically? This is the foundational guide to building a PDF template from a submission. See how to create PDF templates to turn responses into documents.

1. Create a new PDF template: In your project, open PDF templates and create a new template named "Approval audit trail record."

2. Paste the template HTML: Switch to the HTML editor and paste the code below. It pipes in the request and decision fields, plus the real row-ID variable for a unique reference number, and renders the reviewer's typed name as a signature line.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Approval Audit Trail Record</title> <style>   * { box-sizing: border-box; margin: 0; padding: 0; }   body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #ffffff; color: #1a1a1a; }   .page { max-width: 760px; margin: 0 auto; padding: 60px 72px; }   .header { display: flex; justify-content: space-between; align-items: flex-start; padding-bottom: 28px; border-bottom: 1px solid #ececec; margin-bottom: 36px; }   .header-title { font-size: 22px; font-weight: 600; }   .header-sub { margin-top: 6px; font-size: 12px; color: #999999; }   .header-meta { text-align: right; font-size: 12px; color: #999999; line-height: 1.6; }   .header-meta .ref { font-size: 13px; font-weight: 600; color: #1a1a1a; }   .section { margin-bottom: 32px; }   .section-title { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.12em; color: #aaaaaa; margin-bottom: 14px; }   .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 32px; }   .field { padding: 10px 0; border-bottom: 1px solid #f0f0f0; }   .field.full { grid-column: 1 / -1; }   .field-label { font-size: 11px; color: #999999; margin-bottom: 4px; }   .field-value { font-size: 14px; color: #1a1a1a; line-height: 1.5; }   .inset { background: #f9f9f9; border-left: 3px solid #dcdcdc; padding: 16px 20px; font-size: 12px; color: #777777; line-height: 1.6; border-radius: 0 4px 4px 0; }   .signature-name { font-family: Georgia, serif; font-style: italic; font-size: 20px; color: #1a1a1a; border-bottom: 1px solid #d8d8d8; padding-bottom: 10px; margin-bottom: 6px; }   .signature-caption { font-size: 11px; color: #999999; }   .footer { margin-top: 48px; padding-top: 20px; border-top: 1px solid #ececec; display: flex; justify-content: space-between; font-size: 10px; color: #999999; } </style> </head> <body>   <div class="page">     <div class="header">       <div>         <div class="header-title">Approval audit trail record</div>         <div class="header-sub">Official record of a reviewed and decided request</div>       </div>       <div class="header-meta">         <div class="ref">Ref: AUD-@rowid</div>         <div>Submitted @created_at</div>       </div>     </div>     <div class="section">       <div class="section-title">Request details</div>       <div class="grid">         <div class="field"><div class="field-label">Requester name</div><div class="field-value">@requester_name</div></div>         <div class="field"><div class="field-label">Requester email</div><div class="field-value">@requester_email</div></div>         <div class="field"><div class="field-label">Department</div><div class="field-value">@department</div></div>         <div class="field"><div class="field-label">Request summary</div><div class="field-value">@request_summary</div></div>         <div class="field full"><div class="field-label">Description</div><div class="field-value">@request_details</div></div>       </div>     </div>     <div class="section">       <div class="section-title">Decision</div>       <div class="grid">         <div class="field"><div class="field-label">Status</div><div class="field-value">@status</div></div>         <div class="field"><div class="field-label">Decision date</div><div class="field-value">@decision_date</div></div>         <div class="field full"><div class="field-label">Decision rationale</div><div class="field-value">@decision_rationale</div></div>       </div>     </div>     <div class="section">       <div class="section-title">Compliance statement</div>       <div class="inset">This record was generated automatically at the moment a decision was recorded and reflects the request, supporting documentation, and decision rationale exactly as entered. It is preserved as the permanent audit trail for this request.</div>     </div>     <div class="section">       <div class="section-title">Recorded by</div>       <div class="signature-name">@reviewer_name</div>       <div class="signature-caption">Reviewer of record, decision logged @decision_date</div>     </div>     <div class="footer">       <div>Confidential, for internal compliance use only</div>       <div>[Company name]</div>     </div>   </div> </body> </html>

📖 See how to dynamically pull form data into custom emails, PDFs, and AI prompts for the full list of variables like @rowid and @created_at.

3. Save the template: Click Save. You won't attach this to a trigger yet, that happens in Part 5.

Part 5 — Automate the decision: PDF and compliance emails

This is the core of the audit trail: the moment a reviewer records a decision, Formaloo should generate the PDF and notify the right people without anyone touching Send.

💡 Want different emails to go to different people depending on the answer, an approval versus a rejection? This guide covers routing email notifications with conditional rules. See how to send and receive conditional email notifications.

1. Create the compliance record email: Create a new email template named "Decision recorded, compliance record," using the full template below.

Decision recorded, compliance record Subject: Decision recorded, @request_summary (Ref: AUD-@rowid) Body prompt: Write a short, formal email to the compliance inbox confirming a decision has been recorded. State the final status (@status), the reviewer who recorded it (@reviewer_name), and the decision date (@decision_date). Mention that the attached PDF is the official audit record for this decision. Factual, no persuasive language, 2-3 sentences. HTML design: white background, max-width 560px, Inter font, a status badge (green for Approved, red for Rejected) next to the reference number, muted footer #999 noting the PDF is attached. Trigger: When a reviewer changes Status to Approved or Rejected, this immediately generates the audit PDF and sends this email with the PDF attached to the compliance inbox address.

2. Create the requester outcome email: Create a second template named "Decision outcome," using the full template below.

Decision outcome Subject: A decision has been made on your request, @request_summary Body prompt: Write a clear, respectful email to the requester letting them know a decision has been made (@request_summary). State whether it was approved or rejected (@status) and include the reviewer's rationale (@decision_rationale) so they understand the reasoning. If rejected, keep the tone constructive, not final or cold. 3-4 sentences. HTML design: white background, max-width 560px, Inter font, a status badge (Approved = green, Rejected = red), the rationale rendered in a light gray inset block, muted footer #999. Trigger: When a reviewer changes Status to Approved or Rejected, immediately send this email to @requester_email.

3. Add the On update rule: Back in Advanced logicLogic tab, switch to On update, then click Add rule. Set the condition to Status has changed to Approved, grouped with an "or" condition for Status has changed to Rejected.

💡 Want a rule to fire whenever an existing record changes, like a status flipping to Approved? On Update is the trigger for that. See what is On Update logic and how it works.

4. Add the three actions: Add a Generate PDF action and select the "Approval audit trail record" template from Part 4. Add a Send email action for the compliance record template, sent to your compliance inbox address, with the generated PDF attached. Add a second Send email action for the decision outcome template, sent to @requester_email.

5. Save your rules: Click Save in the top right corner.

Part 6 — Build the compliance dashboard and portal

The last piece turns raw submissions into three role-based experiences: requesters tracking their own requests, reviewers working their assigned pipeline, and compliance watching the whole picture.

💡 Want to give clients, applicants, or teammates their own space to submit and track requests? This is the foundational guide to building a portal and controlling who can see it. See how to create a portal and manage users' access.

1. Activate the portal: From your project, click Activate portal.

2. Build the Requesters group: Create a "Submit a request" page with the form, and a "My requests" page showing a table filtered to the logged-in user's own submissions. Add "Approved" and "Rejected" pages using the same filter plus a Status condition.

💡 Want each logged-in user to see only their own submissions, not everyone else's? This is the foundational guide to the "view only their data" access restriction. See how to let users view and edit their own data in your portal.

3. Give requesters portal roles: Open Manage users, run the Setup Wizard, and create a Requester role for external submitters signing up without a Formaloo account.

💡 Want reviewers, approvers, and applicants to each see a different view of the same portal? This guide covers setting up roles so each person only sees what's relevant to them. See how to create and assign user roles in your portal.

4. Build the Reviewers group: Add an "All requests" Kanban board grouped by Status, plus "My assigned requests," "Pending, assigned to me," and "Decisions I've recorded" tables, each filtered to Assignee equals the logged-in user.

5. Restrict reviewer pages by team, not by portal role: Reviewers are internal staff, not external portal users, so they don't get a role through the Setup Wizard. Instead, make sure each reviewer is a workspace member, add them to a "Reviewers" workspace team, then on each reviewer page open the Access menu → Internal usersSpecific teams, and select that team.

💡 Want a whole page in your portal visible only to a specific role, not just specific data within a page? This covers page-level access restriction. See how to restrict users' access to pages in your portal.

6. Build the Compliance & audit group: Add a "Compliance dashboard" page with a chart block tracking approval versus rejection counts grouped by month, an "All decisions" searchable table, and Status-filtered "Pending review," "Approved," and "Rejected" tables plus a "By department" table grouped by Department. Restrict every page in this group the same way as Reviewers, with a "Compliance" workspace team.

7. Add a resources page: Add a "How to use this template" reference page linking to the foundational articles above, so new reviewers have somewhere to start.

Note: You can set a custom domain on your portal, available on the Business plan or via the Brand removal add-on.

What you now have

A single form captures every request with its evidence attached, and a decision made anywhere on that record instantly produces a signed PDF, notifies your compliance inbox, and tells the requester the outcome. Reviewers work their own queue without wading through everyone else's requests, and compliance leadership has a dashboard that turns approvals and rejections into a trend instead of a memory. If an auditor or regulator ever asks who decided what and when, the answer is one search away instead of a week of digging through email.

What's next

Ready-to-use templates

Don't build this from scratch, we've already put it together for you.

  • Employee request workflow — Internal request management for HR and ops teams that routes requests by type and tracks approvals. Swap in the decision fields and On update logic from this article to give it the same audit-ready PDF and dashboard.

  • Scholarship & grant application with scoring and approval — A multi-reviewer scoring workflow that auto-calculates scores and sends approval or rejection emails. The same on-update decision pattern from this article applies directly to its final approval step.

  • Patient intake & consent workflow for healthcare — A two-page intake and consent form with an admin Kanban pipeline and PDF consent document. A regulated-industry example of the same evidence-plus-decision-record pattern this article builds.

Don't have a form yet? Create one in seconds with Magic Create, describe what you need and Formaloo builds the form for you.

Learn more how-tos

Did this answer your question?