What is ActionEquals all about?

ActionEquals is a web service that can process the forms on your website.  It is an easy way to store and retrieve the forms your users submit without writing any server side code (e.g. PHP, Python, NodeJs, Java, etc.).  It handles common scenarios such as Signup (new user registration), Login, CAPTCHA, and more, right "out of the box."  It lets you export these forms to a spreadsheet and download the data.  ActionEquals can make hosting your site on Github Pages or other static repositories, for example, a viable option.  It is also handy for testing-- you can see your web forms working before integrating with or approaching the design of backend services or databases.  In many cases, ActionEquals will provide enough functionality that you will not even need any other  server side programming.

 

Free Means Free

Our Free Trial offer is 100% absolutely free.  We don't even ask for a credit card number.  After your 30-day trial expires, there's nothing to worry about cancelling; you can never be billed.  Plus, the subscription plans we offer are low-priced, flat-rate, month-to-month plans that are easy to cancel at any time.  We won't bother you with junk mail.

 

So, if you're creating questionnaires, surveys, quizzes, contact forms, etc. and are stuck on the <form action="?????????"> or are looking for a solution where you control the look of your site with no programming, then ActionEquals is for you.  

 

Create a Form
You create Form(s) to work with ActionEquals by adding or editing an HTML form on your web pages.  You must register the form name from the Dashboard by clicking Allowed Form Names.. before submissions of that form are processed by ActionEquals.  The “form name” is the value of the f= parameter of the action= url you provide.  This is a security feature that prevents malicious activity and spam.  This documentation has some examples of different kinds of forms in the Example Forms section.

 

Add a CAPTCHA
Add a single line of script after your form:  <script src="https://actionequals.com/getCaptcha/{yourAPIKey}"></script>.

See the CAPTCHA field section.

 

Add a Login (User/Password/Button)
Whether you have an entire Login Page, or just a small set of form fields on your main page, all you need is a simple form with a userid and a password fields as described in the Login Form section.

 

Add a Signup Page
A Login page works in conjunction with a registration form you create to let users create their userids, passwords, and any other data you want to collect from users signing up.  See the Signup Form section for an example.

 

Use the API
The REST API can be used by your application to programmatically create, search for, list, modify, and delete the data submitted to your site by your users.  Our REST API works like many others.  In order to use it, your application needs to be able to create a BasicAuthentication request with your login credentials and send it using the proper HTTP verb (GET, POST, PUT, or DELETE).  This documentation contains full details about all API methods available.

 

Getting More Help
While there's a lot of documentation here that might make all this look complicated, in reality it's very easy to make your site work with ActionEquals.  It can take only a few minutes to do.  Plus, we're eager to help even an absolute beginner achieve whatever your goals are, so that you will recommend ActionEquals to others.  If you need some guidance or have any questions, comments, problems, or other issues, please send an email to support@actionequals.com

 

Overview

ActionsEquals.com is a Forms-As-A-Service that makes it easy to store and retrieve submitted form data.  This documentation will provide many examples and show you how to integrate different kinds of forms on your website with our service.  The data submitted by your users is available for you to view and export by logging into our site and viewing your Dashboard.  A Web API is also provided for use by developers for more advanced integration scenarios.

If you find any feature documented here confusing or difficult, please send us an email at support@actionequals.com describing what you would like to do.  We are always happy to answer any question you might have and provide instructions to help you achieve your desired results.

ActionEquals works the same no matter which server technology you are using (e.g. .NET, Nodejs, PHP, Python, etc.).  It directly and easily supports all kinds of form storage and processing use cases.  In many cases, using ActionEquals can completely eliminate the time and effort needed write any of your own form processing scripts (e.g. /submit.php).  You can create highly-specific and customized forms for a particular site, or consolidate all similar forms across dozens of sites into a single Dashboard view.

  • Input elements of all types
  • TextArea elements
  • Select and Option elements
  • Supports Multiple submit buttons
  • Multi-Step/Multi-Page forms
  • Automatic Password Hashing and Storage
  • Provides a turn-key solution for Login and Signup for your site's users
  • “Out of the box” CAPTCHA solution to reduce spam.  It's the easiest CAPTCHA solution to integrate on the market.
  • Web API for more advanced integration
     

Unfortunately, due to storage requirements, file uploads can be supported only through our Enterprise Plan.  Please contact us if you have this need.

API Key

Before you can use ActionEquals, we need to send you an API Key which you will need even if you will not be making calls to our REST API.

To get an API Key, simply sign up for a free trial.  After your email is confirmed, we will send the API Key to your email address.  You will also be able to view your API Key at any time on the Dashboard Settings page.

Your ActionEquals API key is public and is not used to secure your account or submitted form data.  For this, we use your email address and password which are private.

API Keys are case-sensitive.

If you make a call to Web API method without an API Key, you will receive an HTTP 401 response.

Forms

After designing your form, set the action, name and method attributes of the form tag

method=“post”
action=“https://actionequals.com/form/yourAPIKey?f=formName

For example, suppose your API Key is abc123 and the name of the form is ContactForm.  Then your HTML form tag would look like:

<form method="post" action="https://actionequals.com/form/abc123?f=ContactForm">
   ...
</form>

There are two form names to be avoided when naming your forms:  _Register and _Login (case insensitive).  These form names are reserved for use with our turn-key Signup and Login solutions.

 

Activating the Form

 

In order to activate the form for processing by ActionEquals you must register it by selecting Allowed Form Names.. from the Dashboard and entering the formName.  This will prevent random forms submitted by hackers from spamming your account.

_ForwardUrl

Which page should the user be directed to after they submit the form?  You define this by including a hidden form field named _ForwardUrl.

If your form does not contain this hidden field, the user will be directed to the root url of your website after they submit the form.

 

<input type="hidden" name="_ForwardUrl" value="https://yoursite.com/nextPage.htm"/>

 

If you need to lead the user from one form to subsequent forms, please review the Multiform Wizard example.

 

_ErrorUrl

<input type="hidden" name="_ErrorUrl" value="https://yoursite.com/errorPage.htm"/>

 

If an error occurs during the processing of a submitted form, you can specify the url the user should be directed to.  If your form does not contain this hidden field, the user will be directed to a built-in submission error endpoint which will display a generic error message.

 

Input Fields

Each input field to be stored must have a name property.  This name distinguishes this data element from others in the form.  By default, Input field data is stored as a collection of “miscellaneous” data on a Submission record.  Data in form elements can also be stored in separate columns for sorting, math/computation, or aggregation by following the Field Name Conventions described in a section below.

 

Simple input field:

 

 <input type="text" name="lastName" />

 

The type property of the input tag can be “text”, “number”, “date”, “color”, “email”, “hidden”, “checkbox”, “radio”, etc. according to the HTML standard.  This property is used by the browser to present the desired input control to the user and is not used by ActionEquals.

The type="file " is not currently supported by ActionEquals.  If you require this feature, please contact us for support.

 

Submit Buttons

 

A form usually has only one submit button:

 

<input type="submit" value="Submit" />

 

If you want multiple submit buttons, you can tell which one was used to submit the form by giving them the same name, while letting the display value differ among the buttons:

 

<input type="submit" value="Yes" name="answerButton" />
<input type="submit" value="No" name="answerButton" />
<input type="submit" value="Maybe" name="answerButton" />

 

When viewing the submitted forms in the Dashboard, you will be able to know which button was chosen; “Yes”, “No”, or “Maybe” will be recorded in the “answerButton” slot.

TextArea Fields

Similarly, TextArea fields must have a name property.  As with all other form elements, they can have any other attributes needed for client-side processing and presentation.  For example:

 

<div class='field'>
    <div class='control'>
        <textarea id='Content' name='content' cols='80' rows='40'></textarea>
    </div>
</div>

Select/Options Fields

A Select form field is used to render either a dropdown or a listbox, depending on its size value.  If the multiple attribute is present, the field allows the user to select any number of options.  ActionEquals supports storing the values of the option(s) selected in a single “slot” or column in the created submission.  The select tag must have a valid name property.  For example:

 

<label for="cars">Choose a car:</label>
<select name="cars" id="cars" multiple>
    <option value="volvo">Volvo</option>
    <option value="saab">Saab</option>
    <option value="opel">Opel</option>
    <option value="audi">Audi</option>
</select>

 

Because the multiple attribute is present in the select tag, the user can select many options.  Suppose the user select the first two options and submits the form.  Then the Submission value for the “cars” field will contain “volvo, saab”.

Field Name Conventions

If the name of a form field is recognized as matching our special conventions, ActionEquals will interpret the name as a processing directive to store the field data in a separate column.  Additionally, if stored in a distinct column, you can specify the data type. 

Names to Avoid

Certain element names are reserved as parameter names in our API, or when submitted, have otherwise special meanings to ActionEquals:  DateSubmitted, f, from, key, through and where.

Changing Form Definitions

Once you define a form using the conventions documented in this section, you have essentially created a “schema” for that form that ActionEquals may depend on to control behaviors.  Changing it later may or may not cause problems.  It may be best to change the “name” of the form instead so that forms submitted with the old schema will be stored separately from the forms submitted according to the new schema:

<!-- Initial form definition -->
<form method="post" action="https://actionequals.com/form/abc123?f=ContactForm">
   ...
</form>

<!-- New form definition with added/removed/renamed columns, etc. called "ContactV2" instead of "ContactForm" -->
<form method="post" action="https://actionequals.com/form/abc123?f=ContactV2">
   ...
</form>

Dedicated Columns

As already mentioned, all field data is stored by default in a single multi-valued column of Miscellaneous data that is viewed by clicking the “More..” cell in the Dashboard.  However, fields whose names begin with a capital letter will be stored in a dedicated (distinct, separate) column:

 

name="ColumnName"

Field names are not otherwise case-sensitive.

How do you decide between using the default storage (field name starts with lower-case letter) and a dedicated column (starts with upper-case letter)?  Just as in a spreadsheet, data in its own column is useful for searching and sorting.  If you need to be able to search the submissions for data in that column or sort the submissions in the order of that data, you should choose naming that field with a capital letter.

For example, suppose you have a form that collects the user's ZIP code and you want this data stored in a dedicated column for viewing in the Dashboard, the html for the input tag might look like the following:

 

<input name="ZIP" />

 

This tells ActionEquals to create a dedicated column on the Submission entry called “ZIP” and store the value in that column.  That way, when viewing the submitted records from the Dashboard, or exporting these records to a CSV file, you'll be able to sort them by the data in the the column “ZIP”.

 

Note that multivalued field data (checkboxes with the same name) cannot be stored in a dedicated form field because its value is an array.  ActionEquals will store only the first value of the multiple values in a dedicated field; additional values would be lost.

Field Datatype

By default, submitted data is stored as strings (text).  However, you may have numeric data such as prices or quantities, or date-type data such as birthdates or event dates.  In such cases, you may wish to properly sort this data or perform adding, say, to set a sum total of selected submissions.  You direct ActionEquals to store the data using a particular data type by using the following naming convention for the name property of the field, whether it be an input, textarea, or select field.  For example:

 

name="BirthDate"

name="TransactionNumber"

 

If your field name ends with the substring “Date” or “Number” the data will be stored as a date or a numeric data type.  See also the section for the “Hash” data type for storing passwords.

For example, suppose you want to store the quantity ordered on an order form as a numeric type.  Then the html for input fields might look like the following:

 

<input type="numeric" name="QtyNumber" />

This may seem a little strange, but there's not really an alternative easy way to convey such semantics in html when form data is submitted to a server.  You might know that only the name and value of each form element is submitted to the server as a key/value pair.  All other attributes such as id, type and data-* attributes are not-- they are exclusively for browser rendering and client-side use (css, javascript, label for).

Non-dedicated column data is always stored as string (text).

The name property in the example above directs ActionEquals to create a dedicated column called “Qty” and store the values entered in that column as numbers.

For values submitted which cannot be accommodated by the specified type, ActionEquals will store a null value for this field on the Submission record.

 

Note that numeric data is stored in decimal format to accommodate both integral and fractional (decimal) values.  These values are stored with precision to 4 decimal places.  Both positive and negative numbers can be stored with a range of values from negative to positive 999,999,999,999.99.

 

Date data is stored in YYYY-MM-DD format.

 

Multivalued field data (checkboxes with the same name) cannot be stored in a dedicated form field (column) because its value is an array.  If a form submission with a dedicated column having multiple values in that column is received for processing by ActionEquals, only the first value will be stored in the column.  Any additional values will be discarded.

Hash datatype

The hash datatype is useful for processing the submission of password data so that the originally entered passwords are not stored on our servers. Instead, the submitted data will be run through an algorithm (called the “hash function” to generate a string, and that string (called a “hash”) will be stored instead of the original data.  In order to determine whether a given string, such as a password, matches the stored hash, one would apply the same algorithm to the given string and compare it with the value of the stored hash.  If these values are the same, the password, for example, matches.

 

The hash function used by ActionEquals is called MD5.

 

<input type="password" name="PasswordHash" />

 

If you are looking for a “turn-key” Signup/Registration solution for your site, see the Examples section below.

Alternatively, the ActionEquals Web API can be used to look up form Submissions and obtain field value data.

Key/_DuplicateKeyUrl

Normally, every time a form is submitted, a new Submission is created which you can view from the Dashboard.  However, for certain scenarios such as customer registration, or when a user is limited to one entry, you can use a hidden field named Key to prevent duplicate entries.  Key is a built-in dedicated column.

For example:

<input type="text" name="Key" placeholder="email address" />

 

When the form is submitted, ActionEquals will create a new Submission only if no previous Submission form already exists having the same submitted value.  If a Submission is received with a Key value matching any previously recorded Submission, that Submission will not be recorded (because the purpose of a Submission Key is prevent duplicate Submissions based on key value).  By default, the conflicting Submission will be ignored and the user will be forwarded to the _ForwardUrl without indication.

However if the user should be forwarded to a special page in this case, you can provide an additional directive in the form of a hidden field as described next.

If you want to change an existing form field to be the Key, you should be able to do this without a problem if you make the field required, because all previous submissions will have already been saved with a null Key value.  The duplicate key check will only apply to future submissions.

 

_DuplicateKeyUrl

By default, if you have defined a Key field and a form is submitted with the same value (as a form of the same type) as a previously saved Submission, that submitted form will be ignored in order to preserve the uniqueness of the Key values.  However, you might want to redirect the user to some alternate url if this happens.  For example, suppose you want to limit submissions to one per email address.  To solve this problem, you would define a Key field (as above).  In addition, you would define a _DuplicateKeyUrl as below:

<input type="hidden" name="_DuplicateKeyUrl" value="https://yoursite.com/WeAlreadyReceivedYourEntry.html" />

Note that the use of _DuplicateKeyUrl is incompatible with Multipage Forms as described in the next section.

_MultiPage Directive

You can design a questionnaire, wizard, etc., consisting of multiple related pages with Back/Previous and Next buttons such that the data submitted on these separate pages will be collected under a single “submission” record when viewed in Dashboard.  In this scenario, multiple forms with the same form name are created, each with different fields.  Our Wizard example later in this documentation shows how to do this.

This requires that each of these forms has a hidden input field named _Multipage.

<input type="hidden" name="_Multipage" value="true" />

As documented by the Multiform Wizard Example section, these multiple form pages need to be associated with one another by the value of the Key.  Since the data submitted on several pages are to be stored together as a single Submission record, the _Multipage field is conceptually incompatible with the use of a _DuplicateKeyUrl field.  If you define both a _DuplicateKeyUrl field and a multipage field, the _DuplicateKeyUrl will be ignored.

CAPTCHA field

For your convenience, ActionEquals provides you with an optional feature to generate a CAPTCHA field on a form and automatically validate it when submitted.  This is especially useful for forms exposed to the general public.  Such forms are often “spammed” with unsolicited marketing or malicious submissions.  You can either use your own CAPTCHA or use ours.

 

In order to use a CAPTCHA provided by ActionEquals;

 

Add the following script tag to the body of your page (replacing {yourAPIKey} with your APIKey 

<script src="https://actionequals.com/getCaptcha/{yourAPIKey}"></script>

 

For automatically styling, you can add this placeholder div  which ActionEquals will replace with the CAPTCHA challenge:

<div class="captcha"></div>


Otherwise, when the Javascript executes, it will inject a div tag into your form which you can optionally style using CSS.  This div will contain the CAPTCHA image (png) depicting 5 upper and lowercase letters and digits and an input to accept user input for matching the image.

 

If the user fails the CAPTCHA challenge, they will be redirected back to the URL from which they came, which should be your form.

Dashboard

When logged into ActionEquals, the Dashboard is your view by default.

If you are logged out or don't have an account, you can see the sample Dashboard here:  /Dashboard 

If you are logged in, but want to see the TEST account Dashboard instead of your Dashboard, click the “Test Account Dashboard” link.

If you are viewing the TEST account Dashboard and you are logged in, you can switch back to your Dashboard by clicking the “Switch back to My Dashboard” link.

The sample contains data collected from all the sample forms (purged regularly) in this documentation.

 

Left Panel

The list of all form types submitted appears in the Left Panel.  By “form type” we mean the formName argument of the action= url on the form tag. For example, if your site has two different form pages, you will see two Forms in the Left Panel:  ContactForm and CustomerSurvey

 

Right Panel

The data submitted for the Form selected in the Left Panel will be displayed in the Right Panel grid.  The Date column is provided automatically and contains the date and time the submission occurred (UTC).  Any Dedicated Fields you have defined (see Field Name Conventions) will appear next from left to right.  The rightmost column will display “More..”  This is where all the “miscellaneous” (non-dedicated field) data can be viewed. By clicking on “More..” a table will be displayed in the an overlay containing the field names and values for all of the data captured.

 

Download

By clicking on the “Download as .csv file” a comma separated value format file is constructed containing all Submissions for the selected Form and download begins automatically.  You can open this file in any spreadsheet program such as Microsoft Excel.

 

Delete Form

By clicking on “Delete This Form” all form submissions for the selected Form are deleted.  (This is non-functional in the sample Dashboard.)

 

Settings
From the settings page you can change your login credentials, view your account status, upgrade your plan, cancel your account, and make a payment.

Logout

After selecting Logout, you will not see the Dashboard view until you're logged in again.

Limitations

There is currently no limit on the number of different forms nor the number of submissions recorded per form type.  Our current limitations are only regarding the number of “dedicated" fields (per form type) you can have of each each data type.  As previously mentioned, a dedicated field is one which appears as its own column in the Dashboard view for a form by using the naming convention documented above.  Please note, there is no limit to the number of form fields, only dedicated fields, which is as follows:

 

Maximum of 5 dedicated text fields per form not including the Key, if any

Maximum of 4 dedicated number fields per form

Maximum of 3 dedicated date fields per form not including SubmittedDate

 

There is a difference between the data storage limits for dedicated text fields vs. miscellaneous text fields.

A Dedicated Text field can contain no more than 256 characters.

The cumulative storage limit for all miscellaneous (non-dedicated) fields together is 16Mb per form submission.

Example Forms

This section shows some example HTML forms using ActionEquals with various features.  The API Key used in all the examples is ‘TEST’.  Please note that test submissions for the example forms can be purged at any time.

Contact

Most websites have a Contact Form through which visitors or potential customers can leave messages and information about what they are interested in and how to get back to them.

This example demonstrates a form that collects the following information from users:

FieldDedicated?Data TypeForm Element
namenotextinput text (required)
Emailyestextinput email (required)
phonenotextinput tel
SelectionNumberyesnumberselect
commentsnotexttextarea

 

Notice that the fieldnames “Email” and “SelectionNumber” are capitalized.  This tells ActionEquals to record the data collected in these fields into individual columns, separate from fields “name”, “phone” and “comments” which will be stored together in the Misc Data column.  The CodePen.io below shows the html needed for a Contact form integrated with ActionEquals.  (The javascript just moves the CAPTCHA inside the form for aesthetic reasons).

 

Notes:

 

form actionhttps://www.actionEquals.com/form/TEST?f=Contact
form methodMust be “post”
input, select, textareaEach must have a name
CAPTCHAInjected into the form by the “getCaptcha" script tag

In practice, you will also provide a _ForwardUrl and optionally an _ErrorUrl to send the user to after the submission is recorded by ActionEquals.

See the Pen Contact Form by ActionEquals (@jdabulis) on CodePen.

Satisfaction Survey

Another common use case is a customer satisfaction survey.

 

FieldDedicated?Data TypeForm Element
WouldRecommendNumberyesnumberinput radio
Overallyestextinput radio
serviceDescriptionnotextinput checkbox
commentsnotextinput text

 

  • checkbox fields which have the same name allow the user to select any number of items.  A multivalued field is array, not a single value of text or numeric type.  Arrays of values are always stored in a regular (the "More.." or miscellaneous data collection) field.
  •  

The CodePen below shows the html and css for this form.

 

ActionEquals Specific:

 

form actionhttps://actionequals.com/form/{your API Key}?f=Survey
form methodPOST
input elementsnamed according to conventions

You should also provide hidden input elements named _ForwardUrl and _ErrorUrl to which the user will be directed after submitting the form.

See the Pen Survey by ActionEquals (@jdabulis) on CodePen.

Multiform Wizard

Instead of creating one large form with many input fields, you can separate the form into smaller pages such that when a user answers question(s) on one page, they proceed to the question(s) on the next page.  Of course, you could implement this user experience with client-side javascript, but ActionEquals makes it easy to implement this scenario without the need to write your own javascript.  By using Key and _ForwardUrl input elements, ActionEquals will collect the form data from multiple related forms ("wizard") into a single submission as viewed from the Dashboard.

 

You can run the example wizard in a new window by clicking here.

Page 1

The wizard takes the user through three form pages.  The code below contains the form html and the script used to unite the three form pages.

 

    <form action="https://actionEquals.com/form/TEST?f=Jewelry" method="post">
        <input type="hidden" name="_ForwardUrl" value="https://actionEquals.com/jewelry2.htm" />
        <input name="_Multipage" type="hidden" value="true" />
        <input id="correlationId" type="hidden" name="Key" value="" />
        <h3>What kind of jewelry do want to purchase?</h3>

        <input id="necklace" name="JewelryType" type="radio" value="Necklace" />
        <label for="necklace">Necklace</label><br>

        <input id="bracelet" name="JewelryType" type="radio" value="Bracelet" />
        <label for="bracelet">Bracelet</label><br>

        <input id="earrings" name="JewelryType" type="radio" value="Earrings" />
        <label for="earrings">Earrings</label><br>

        <input type="submit" value="Next >>" />
    </form>
    <script>
        eraseCookie("correlationId");
        var guid = uuidv4();
        createCookie("correlationId", guid);
        
        document.getElementById("correlationId").value = guid;

        function uuidv4() {
            return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
                (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
            );
        }

        function createCookie(name, value, days) {
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                var expires = "; expires=" + date.toGMTString();
            } else {
                var expires = "";
            }
            document.cookie = name + "=" + value + expires + "; path=/";
        }

        function eraseCookie(name) {
            createCookie(name, "", -1);
        }
    </script>

 

Notes:

  • TEST is the test api key
  • Jewelry is the name of the set of forms and must be the same for all wizard pages.
  • A hidden _Multipage element with value “true” indicates that this form is part of a set.
  • A hidden Key element is defined.  When the script runs, a unique identifier is randomly generated and stored in a cookie.  This value is then also assigned to the Key.  That way, when subsequent wizard pages are presented, each can read this cookie value-- all forms in the set are submitted using the same Key value.  Remember that when ActionEquals receives multiple submissions for a form type with the same Key, it does not create a new Submission record.  Instead, it updates the existing record found with that Key.
  • Three radio buttons are created (for Necklace, Bracelet, and Earrings)-- the user's submitted choice should be stored in a dedicated field called JewelryType.
  • The submit button displays “Next >>” because the _ForwardUrl specifies that after the form is submitted, the user should be presented with the jewelry2.htm form documented below.

Page 2

The code for the second wizard page (jewelry2.htm) is similar:

<form action="https://actionEquals.com/form/TEST?f=Jewelry" method="post">
        <input type="hidden" name="_ForwardUrl" value="https://actionEquals.com/jewelry3.htm" />
        <input name="_Multipage" type="hidden" value="true" />
        <input id="correlationId" type="hidden" name="Key" value="" />
        <h3>Select a Metal:</h3>

        <input id="gold" name="Metal" type="radio" value="Gold" />
        <label for="gold">Gold</label><br>

        <input id="silver" name="Metal" type="radio" value="Silver" />
        <label for="silver">Silver</label><br>

        <input id="platinum" name="Metal" type="radio" value="Platinum" />
        <label for="earrings">Platinum</label><br>

        <input type="button" class="button" value="<< Previous" onclick="window.history.go(-1); return false;" />
        <input type="submit" class="button" value="Next >>" />
    </form>

    <script>
        var guid = readCookie("correlationId");
        document.getElementById("correlationId").value = guid;

        function readCookie(name) {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');
            for (var i = 0; i < ca.length; i++) {
                var c = ca[i];
                while (c.charAt(0) == ' ') {
                    c = c.substring(1, c.length);
                }
                if (c.indexOf(nameEQ) == 0) {
                    return c.substring(nameEQ.length, c.length);
                }
            }
            return null;
        }

    </script>

 

Notes:

The same form action is used for all three wizard pages.

The _ForwardUrl for the second page directs the user to jewelry3.htm

The _Multipage and Key elements are defined the same way for all three pages.

Another group of radio buttons are defined to collect the choice into a dedicated form field called “Metal”.

A “<<Previous” button is defined that simply sends the user back to the previous page using inline Javascript.

The script reads the cookie created on the first page and stores it as the value of the Key, just as on the first page.  

Page 3

The third page of our wizard asks the user to select a color from a color wheel using a JQuery plugin called Farbtasic.  It is very easy to use such client side plugins with ActionEquals giving you countless look-and-feel possibilities to write forms any way you want-- we just store the data submitted.

 

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>

    <script src="js/jquery-1.11.3.min.js"></script>
    <script type="text/javascript" src="/farbtastic/farbtastic.js"></script>
    <link rel="stylesheet" href="/farbtastic/farbtastic.css" type="text/css" />

    <style>
        h3 {
            font-family: sans-serif;
        }
        .button {
            background-color: green;
            color: white;
            font-size: larger;
        }
    </style>
</head>
<body>

    <form action="https://actionEquals.com/form/TEST?f=Jewelry" method="post">
        <input type="hidden" name="_ForwardUrl" value="https://actionEquals.com/jewelry4.htm" />
        <input name="_Multipage" type="hidden" value="true" />
        <input id="correlationId" type="hidden" name="Key" value="" />
        <h3>Select a Gem Color:</h3>
        <input name="Color" type="text" id="color" class="swatch" value="#ffffff" />
        <div id="colorpicker"></div>

        <input type="button" class="button" value="<< Previous" onclick="window.history.go(-1); return false;" />
        <input type="submit" class="button" value="Done" />
    </form>

    <script>
        var guid = readCookie("correlationId");
        document.getElementById("correlationId").value = guid;

        function readCookie(name) {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');
            for (var i = 0; i < ca.length; i++) {
                var c = ca[i];
                while (c.charAt(0) == ' ') {
                    c = c.substring(1, c.length);
                }
                if (c.indexOf(nameEQ) == 0) {
                    return c.substring(nameEQ.length, c.length);
                }
            }
            return null;
        }

        $(document).ready(function () {
            $("#colorpicker").farbtastic(".swatch");

        });

    </script>
</body>
</html>

 

The form defines a dedicated form field-- “Color” into which color hex values (e.g. #2ea87b) will be stored.  A feature of ActionEquals is that values of this format are automatically recognized as colors by the Dashboard view and displayed as the background color of data cells.  The TEST account dashboard (Jewelry form) demonstrates this feature.

 

Jewelry4.htm is merely a landing page to display when the user has completed the wizard and contains no form fields.

Turn-Key Scenarios

In the examples that follow, we show you how to implement a User Signup form and a Login form that leverages ActionEquals as your User database.

Signup Form

Many websites have a “Signup” or registration feature that allows users to enter a user id such an email address, a password, and perhaps other information such as their Name, Country, etc.  This record is later used by the website to enable registered users to login and access additional site pages and features.

 

If you are creating a new site or if you need to add a user Signup form, ActionEquals provides a simple way to accomplish this.  Below is an example of an HTML form that integrates with ActionEquals built-in Registration feature:

 

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <link href="css/bulma/css/bulma.css" rel="stylesheet" />
</head>
<body>
    <form method="post" action="https://actionEquals.com/form/APIKEY?f=_Register">
        <input type="hidden" name="_forwardUrl" value="members-only-page.htm" />

        <div class="card" style="width:400px;">
            <div class="card-header">
                <p class="card-header-title">
                    Register as a Member
                </p>
            </div>
            <div class="card-content">
                <div class="field">
                    <div class="control">
                        <label for="user">Username</label>
                        <input id="user" type="text" name="userid" required />
                    </div>
                </div>

                <div class="field">
                    <div class="control">
                        <label for="pwd1">Password</label>
                        <input id="pwd1" type="password" name="password" minlength="6" required />
                    </div>
                </div>

                <div class="field">
                    <div class="control">
                        <label for="pwd2">Re-enter Password</label>
                        <input id="pwd2" type="password" name="password2" minlength="6" required />
                    </div>
                </div>

                <div class="field">
                    <div class="control">
                        <label for="dbo">Date of Birth</label>
                        <input id="dob" type="date" name="BirthDate" />
                    </div>
                </div>

                <div class="field">
                    <div class="control">
                        <input type="submit" value="Submit" />
                    </div>
                </div>
            </div>
        </div>
        
    </form>
</body>
</html>

 

To see it in action in a new window, click here.

 

Notes:

 

  1. Your form should POST to action="https://actionEquals.com/form/APIKey?f=_Register" where APIKey is your API Key.
  2. The _forwardUrl value specifies the Url that the user will be redirected to after successfully submitting the registration form.  If the form is not successfully submitted, for example, if the passwords do not match, etc., the user will be redirected to the _errorUrl.  The error message will be appended to the errorUrl as an error= querystring argument, in case your server script can make use of it.  The _errorUrl hidden element is optional; if you do not provide it and there is an error in processing the _Register form, the user will be sent to a generic error page page provided by ActionEquals which will show the errorMessage and invite the user to click a button to return to your _Register form.
  3. Your form must have a required input with name="userid".  For example: <input name="userid" required />.  Its type can be text or email, for example.
  4. Your form must have two required input elements named password and password2.  This is the password the user selects to create their membership record for subsequent login.  You are obviously free to perform client-side validation, but this is optional. When submitted to ActionEquals, we will validate these password fields to ensure they match and are at least 6 characters in length.  You may require a password of any length greater than 5 characters-- we require the password to be at least 6 characters.  If you have additional password complexity requirements, you must implement them client-side in javascript.
  5. For everyone's security, we do not store any actual passwords, but an cryptographic hash of the password received.  No one will be able to obtain a user's password.
  6. Your form can optionally define additional fields just like a standard ActionEquals-compatible form.  The example above asks the user for their date of birth.  Because the name of the field is BirthDate (starting with a capital letter), the collected birthdates will be stored in a dedicated column (see Dedicated Columns section).  This field data will be stored on the _Register submission just like ordinary forms.

 

REST API users should note that the userid of each _Register form submission gets stored in the Key field.

Login Form

A login form makes sense once you have some kind of registration form to collect that data in the first place.  With just a few lines of HTML and no server-side programming, you can add a Login <form> to your website that automatically works with the user registration <form> you set up described above.  To test out the example form below click here. (You can register a new test user by running the Register example above or you can test logging in with user id TestUser, whose password is Pa$$w0rd.  Try a bad username/password too.)

 

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <link href="css/bulma/css/bulma.css" rel="stylesheet" />
<script src="https://actionequals.com/login/{APIKEY}" defer></script>
</head>
<body>
    <form method="post" action="">
        <input type="hidden" name="_forwardUrl" value="members-only-page.htm" />

        <div class="card" style="width:400px;">
            <div class="card-header">
                <p class="card-header-title">
                    Login
                </p>
            </div>
            <div class="card-content">
                <div class="field">
                    <div class="control">
                        <label for="user">Username</label>
                        <input id="user" type="text" name="userid" required />
                    </div>
                </div>

                <div class="field">
                    <div class="control">
                        <label for="pwd1">Password</label>
                        <input id="pwd1" type="password" name="password" minlength="6" required />
                    </div>
                </div>

                <div class="field">
                    <div class="control">
                        <input type="submit" value="Submit" />
                    </div>
                </div>

            </div>
        </div>
    </form>
</body>
</html>

 

Notes:

 

  1. Your form should POST to action="https://actionEquals.com/form/APIKey?f=_Login" where APIKey is your API Key.
  2. The _ForwardUrl value specifies the Url that the user will be redirected to after successfully submitting the login form.  If the form is not successfully submitted, for example, if the passwords is incorrect etc., the user will be redirected to the ErrorUrl.  The error message will be appended to the errorUrl as an error= querystring argument, in case your server script can make use of it.  The _ErrorUrl hidden element is optional; if you do not provide it and there is an error in processing the _Login form, the user will be sent to a generic error page page provided by ActionEquals which will show the errorMessage and invite the user to click a button to return to your Register form.
  3. Your form must have a required input with name="userid".  For example: <input name="userid" required />.  Its type can be text or email, for example.
  4. Your form must have a required input with name="password".
  5. If your login form has additional fields, these are ignored by ActionEquals.

 

REST API users should note that the userid of each _Login submission is its Key.

Login Protected Pages

Once you have implemented the registration and login forms, you can ensure that only logged-in users are able to view the content on other pages of your site.  To do this, add the following to the <head> tag of the protected page

<head>
    ...
    <script src="https//actionequals.com/protect/{APIKEY}"><script>
</head>


Inside the <body> and before the closing </body> tag, insert the following:

<script>
    window.onload = async function() {
        let userId = await loggedInUser();
        if (!userId) {
            window.location.href = "{url to page if user is not logged in}";
        }
    }
</script>


for example:  window.location.href = "index.html"


Note:  If a user is logged in, the there will be a cookie "userid" whose value is the user id of the logged in user.

REST API

The REST API which uses Basic Authentication, is designed to be used by web developers expert in implementing integrations.  Methods should not be invoked directly from web pages using JavaScript.

The email address and password you used to sign up with ActionEquals also serve as the username and password (BasicAuthentication) credentials for REST API authentication purposes.

All REST API methods expect to receive a valid Authorization header according to the standard for Basic Authentication.  In basic HTTP authentication, a request contains a header field in the form of Authorization: Basic <credentials>, where credentials is the Base64 encoding of ID and password joined by a single colon :

You can use a utility such as Postman to create and inspect REST API requests with a "Basic Auth" header and the desired HTTP verb.

The following table lists the API methods currently available and the purpose of each:

Documentation SectionHTTP VerbUrl Pattern (endpoint)Purpose
Get By KeyGEThttps://actionEquals.com/api/{Api Key}?f={form name}&Key={submission key}

Retrieve a single form submission (JSON), or

Retrieve a registered user's account record (Turn-key Signup)

Get AllGEThttps://actionEquals.com/api/{Api Key}?f={form name}Retrieve all form submissions
QueryGEThttps://actionEquals.com/api/{Api Key}?f={form name}Search for and Retrieve form submissions by query expression.
Create SubmissionPOSThttps://actionEquals.com/api/{Api Key}?f={form name}Create a new form submission (programmatically)
Delete By KeyDELETEhttps://actionEquals.com/api/{Api Key}?f={form name}&Key={submission key}

Delete a form submission by its unique key, or

Delete a registered user (Turn-key Signup)

Delete RangeDELETEhttps://actionEquals.com/api/{Api Key}?f={form name}&start={date1}&end={date2}Delete all form submissions within an (optional) range of dates.
Update By KeyPUThttps://actionEquals.com/api/{Api Key}?f={form name}&Key={submission key}

Update the data for a form submission, or

Update a registered user's account record

Turn-Key LoginPOSThttps://actionEquals.com/api/Login/{Api Key}Turn-key Login programmatically log in user
Turn-Key SignupPOSThttps://actionEquals.com/api/Signup/{Api Key}Turn-key Signup programmatically create new user

Some API method request expect or allow a content payload.  You can send the request content either as multipart/form-data, application/x-www-form-urlencoded, or application/json according to your preferences.

Unless otherwise noted, the following are the HTTP error status codes you could receive and the typical reasons for the errors:

HTTP Status CodeReason
400Required argument (e.g. form name) was not provided or contained an invalid, badly formatted, or empty value
401The BasicAuthentication Authorization header was missing or invalid or the Api Key was not provided.  Note that Api Key is case sensitive.
403Your account status is inactive or trial period has expired.
404The form name was not found or a GET request did not find requested Submission records (i.e. no matching Submission key value).  Note that form names are case sensitive.

Get By Key

Url Pattern:  api/{API Key}?f={FormName}&Key={SubmissionKey}

VERB:          GET

Response:   JSON representation of form submission data (Field-Value pairs)

 

Example Request:

GET https://actionEquals.com/api/{your APIKEY}?f=Contacts&Key=bart@yahoo.com

 

Example Response:

{ "DateSubmitted": "2020-11-25T10:11:06",
  "SubmissionKey": "bart@yahoo.com",
  "contactReason": "Pre-sales"
}

Since property contactReason starts with a lower-case letter, then according to the naming conventions, this data will be stored in the “miscellaneous” (JSON object) submission record column.

Get All

Url Pattern:  /api/{Api Key}?f={FormName}

VERB:          GET

Response:   Array of JSON objects

 

Returns all form submissions for form type FormName.  To find only the submissions matching search criteria (e.g. DateSubmitted within some range of dates), add the where parameter documented in the section below.

 

Query

Url Pattern:  /api/{Api Key}?f={FormName}&where={queryExpression}

VERB:         GET

Response:   Array of JSON objects (HTTP Status Code 200)

 

Searches for form submission matching a query expression.

The value of where is a logical expression (i.e. a predicate).  All Submissions for which the expression evaluates to true will be returned.  Legal expressions contain only dedicated field names and value literals, comparison operators (= or ==, >, >=, <, <=, != or <>, and StartsWith()), Boolean operators AND, OR and parentheses as necessary, according to the following rules.

 

Request Examples (JSON in Body)

{"where": “Name=John”}
{"where": "Name == Jim's Garage"}
{"where": Name StartsWith Fred}
{"where" : Name >= ‘S’}
{"where": DateSubmitted StartsWith '2020-09'}
{"where": (Amount > 29.99 AND Amount <= ‘59.99’)}
{"where": ((Key == ‘a@b.com’ AND DateSubmitted <> 2020-04-15) OR (price < 2))}

You can also send the query expression in a x-www-form-urlencoded request body or a multi-part/form-data request body:


Field names can be dedicated column names, or “DateSubmitted” or “Key”.  

Field values must be delimited by single or double quotes if they contains spaces.  Date literals are of the form YYYY-MM-DD.  

If there is some syntax error in the query (e.g. no such dedicated form field, mismatched parentheses, etc.), you will receive an HTTP 400 response.

Either matching single or double quotes can be used to delimit values and are required for values containing blank spaces.

The field names themselves are not quoted.

Create Submission

Url Pattern:  /api/{Api Key}?f={FormName}

VERB:          POST

Creates a new Submission of a FormName type form.  If a Key field value is sent and that value matches an existing submission, you will receive an HTTP 400 response, because if you want to update an existing record, you must send a PUT request instead.

For the following example, assume we want to programmatically POST submissions to a “Pet” form with the following desired fields:

Column dataData TypeDedicated Column?JSON Property Name
Unique idstringspecial/built-inKey
Animal NamestringNoname
Animal TypestringYesAnimalType
PricenumericYesPriceNumber
Has shots?stringYesHasShots

Note that same field naming conventions are use as with HTML forms.  You can send either form data or json data (application/x-www-form-urlencoded, application/json, application/javascript, text/plain or multipart-formdata).

 

Response:    HTTP Status Code 200 (with no content) or error status code with error message content.

 

Delete By Key

Url Pattern:  api/{API Key}?f={FormName}&Key={SubmissionKey}

VERB:          DELETE  (Note: TEST records are not deleted)

Deletes a single Submission record matching the unique Key value.

 

Example Request (Query string):

DELETE https://www.actionEquals.com/api/{Your API Key}?f=Contacts&Key=bart@yahoo.com

Response:  HTTP Status Code 200 with the message “Record deleted” or error status code with error message content (e.g. 404 if no matching record was found).

Note:  You can also send the key in Body as JSON or a form field (key=value)

 

Delete Range

Url pattern:  api/{API Key}?f={FormName}

VERB:          DELETE  (Note: TEST records are not deleted)

Delete ALL form submissions of the given FormName. If date parameters from and/or through are sent in the request body, only Submissions on, before, after, or within the date(s) given will be deleted.

For example, to delete ALL submissions of the “Jewelry” form, you would send an HTTP DELETE request.  The from and through parameters are compared the the DateSubmitted record column which is automatically populated whenever a Submission record is created.

 

Delete ALL Example Request URI

https://actionEquals.com/api/Your-API-Key?f=Jewelry

 

If you wanted to delete only the Jewelry submissions before July 2020 you would send the through argument.  You would supply a date in the Body of the request.

Delete Range Example JSON body (application/json content type):

{ "through": "2020-06-30" }

 

If you wanted to delete only the Jewelry submissions on or after August 1, 2020, you would send the from argument.  

Delete Range “form data” style (x-www-form-urlencoded or multipart/form-data) request:

from=2020-08-01

 

Delete Range JSON example:  To delete all records between two dates, send both from and through arguments

{ "from": "2020-03-01", "through": "2020-03-10" }

 

Besides sending the from/through parameters in the Request Body with the ContentTypes above, you could also send parameters on the Querystring:

https://actionEquals.com/api/Your-API-Key?f=Jewelry&from=2020-08-01&through=2020-03-10

Dates are inclusive.

 

Response (HTTP 200 if successful with a message containing the number of Submissions deleted, otherwise error code/message.

 

Update By Key

Url pattern:  /api/{Api Key}?f={FormName}Key={SubmissionKey}

VERB:          PUT

The POST method documented above in the “CreateSubmission” section will create either a new Submission record or it will fail because an existing Submission record exists with the requested Key.  If you want to overwrite fields on the matching Submission Record, send an HTTP PUT request instead.  Otherwise, these methods are the same as the POST method with regard to request and response.

Send only the fields you want to change the values of.  You can set/overwrite  the value of a text or a date field to null.  For example:

 

{ "Name": null }

 

If you send a PUT request and no Submission record matching the requested key value is found, you will receive a 404 response.  You should send a POST request instead.  If you don't know whether the requested resource already exists in order to determine whether to sent a POST or a PUT request, you should first send a GET request

 

Any attempt to change the Key by supplying a value for this field will be ignored; a key cannot be changed.

Turn-Key Login

api/Login/{API Key}

If you use the Register API method or the Turn-Key Signup to register new users, you can also use the Login API to programmatically determine whether a registered user logs in with a given userid and password.

Headers:    BasicAuthentication (Requires “Authorization” HTTP Header)

Method:  POST (application/x-www-form-urlencoded)

Example request (form data):

userid=Miles Perowa&password=sushi1

 

The request must contain fields userid and password.  

 

If login is successful, you will receive an HTTP 200 response with an object containing any additional miscellaneous data associated with the Submission found (see Register API below).

Example response:

{
	"myAdditionalDataItem1": "FooBar"
}

 

If your Authorization header is missing or incorrect, you will receive an HTTP 401 response.

If there is some problem with your account, you will receive an HTTP 403 response.

If the userid or password is missing, null or empty, you will receive an HTTP 400 response.

If no user with the userid is found or the password does not match, you will receive an HTTP 404 response with an error message such as “User not found” or “Password is incorrect”

If you receive some other error response code, please contact support.

Turn-Key Signup

Url Pattern:  api/Signup/{API Key}

VERB:           POST

Create new Register Submission compatible with the Turn-Key Login solution.

 

Example Request Body (application/x-www-form-urlencoded)

userid=fcarkers@protonmail.com&password=sushi1&FavoriteColor=Black

The request must contain fields userid and password.  The password must be at least 6 characters in length.

The MD5 hash of the password is stored, not the plain-text password.

The request may contain additional fields.  The data in these fields will be stored on the user's Submission record (field naming conventions documented earlier are applied).

If the userid or password is missing, null or empty, you will receive an HTTP 400 response.

It is an error to submit a userid that already exists.  You will receive an HTTP 400 response with a "Username already taken" error message.

If the registration is successfully created, you will receive an HTTP 200 (OK) response.

 

To Update a Register Submission (i.e. a user record), send a PUT request according to the “UpdateByKey” section above instead of a POST.  The formName is “_Register” and the key is the userid.  Include only the fields whose values are to be changed.  For example, sending the content:

password=asdfasdf

to https://www.actionEquals.com/api/FOOBAR?f=_register&Key=fcarkers@protonmail.com changes the user's password.

 

Similarly, to Delete a register record, send a DELETE request according to the “DeleteByKey” section above.  The formName is _Register and key is the userid.