A LIST Apart: For People Who Make Websites

No. 297
December 8, 2009

Letting Go of John Hancock

Letting Go of John Hancock

As competition strengthens, every step is vital in making or breaking a deal. Because clients expect everything to be faster, better, and simpler, web professionals must take an instant, foolproof, paperless, modern approach to how clients approve proposals and sign contracts. These documents speak volumes: After all, they are often your first chance to showcase your approach to doing business. I have a way to allow clients to submit legally binding signatures through a web page or PDF file—preserving the classic “signature” aspect while eliminating the most archaic requirements of many modern proposals and contracts. Let’s see how it works.

Disclaimer: I am a website professional, not a lawyer, and am not attempting to provide any legal advice in this article. Please consult a legal professional in your jurisdiction should you have specific legal questions.

Legal validity of electronic signatures

What does a “signature” require to be legally binding and hold up in court? I consulted my attorney Tom Roth of Steinmeyer Roth LLP, who e-mailed me some comforting news:

Even with a notary verifying a signature, there is no guarantee [of legal impunity], as I have litigated cases in which the notary improperly ‘verified’ a signature of a person who in fact did not sign the document...the California Courts need only find ‘acceptance’ of the contract to determine it is binding...For instance if I send you a letter stating ‘we agreed that you shall pay our law firm $1,000,000,’ if I can demonstrate that you received the letter and did not object, the Court can make a judgment in my law firm’s favor for the $1M. A person’s proactive conduct, i.e., pressing the ‘accept’ link or ‘I agree’ button, is also more than sufficient to make a binding contract. The threshold for finding acceptance is rather low—you need not focus on the ‘signature’ aspect of the contract.

In other words, “acceptance” is not necessarily about the signature at all. While signing is a traditional and familiar way to signify acceptance, by itself it offers no guarantees. However, contract acceptance is implied when a follow-up e-mail comes from either party, you receive a down payment, the client sends files to you, or any other action outlined in the contract takes place. Let’s explore a way for clients to signify their acceptance electronically.

What we need—a document format that can post data

PDF allows form elements to transmit data to a web page. Basically, a client can review a PDF proposal or contract, fill it out on the fly, and submit it instantaneously—all through Acrobat. I’m willing to bet that most website professionals already send out proposals and contracts in PDF format, and that most potential clients have Acrobat Reader installed. Expanding a PDF file to include form fields that may be filled out and posted to a web page is easy. And, we can even generate and display a PDF receipt automatically upon acceptance, which clients can save or print. All we need to do is set up a form inside a PDF proposal or contract, create a web page to post the data to, and create a PDF receipt template. We can do it using Acrobat Professional and some PHP.

Expanding a PDF proposal or contract

To add an interactive form to your PDF, open the finished proposal or contract in Acrobat Professional, click “Forms,” then choose “Start Form Wizard.” Select the current document. Now, you’re in “Form Editing” mode. Upon entering this mode, Acrobat will attempt to detect anything that already resembles a form label (text followed by an underline) and create corresponding input fields automatically. You can add familiar form elements manually via the “Add New Field” button at the top left of Acrobat. You can edit form element properties by right-clicking on each element.

You may need to insert more fields or edit the added fields so that their name attributes are unique, appropriate, and can be referenced later. The PHP file that receives this data will associate $_POST variables based on the “name” attribute of these elements—just like an HTML form posted from a web page to PHP.

Set all your input fields to “Required” by right-clicking, then choosing “Properties.” Add a hidden field named “proposal_id” and assign an appropriate, identifying value to each proposal. Include a plain text proposal with a link to a web page that contains an HTML version of the same form. This ensures that the agreement can be immediately accepted by the few people who might not have or have access to Acrobat Reader.

Finally, insert a button element to create an “Accept” button. Under the “Actions” tab of the button’s properties, change the trigger to perform the “Submit a Form” action. In the dialog box that appears, enter the URL where your PHP page that processes the data resides, then choose “HTML” as the export format.

Setting up a PDF receipt template

It’s easy to set up a PDF template that can be filled in dynamically. Simply create a new PDF document and add read only “Text Fields” containing “name” values that correspond to those in your PDF proposal. For example, if the proposal has an input field named “proposal_id,” the PDF template will populate a hidden field named “proposal_id” with the corresponding posted variable. For the viewer’s sake, create labels that identify the hidden fields. While the template is still open, click the “Advanced” tab and choose “Extend Features in Adobe Reader.” Now, clients can save each receipt the template generates using Acrobat Reader—something they would otherwise need Acrobat Professional to do. Lastly, we publish the template to a location that clients may access—referred to as “http://example.com/receipt.pdf” later, in our PHP file.

PDF accessibility

Before we finish with the PDF files, it’s important to address PDF accessibility. Make these PDF proposals and receipts accessible with the same enthusiasm you use to make web pages accessible. Luckily, you can structure and mark up PDF documents similarly to the way you mark up HTML documents. Acrobat has tools to check file accessibility. While PDF accessibility is beyond the scope of this article, most basic proposals will require a language specification, tags, and form field descriptions.

Creating a PHP file to process the submission

The PHP file expects six $_POST acceptance variables (name, e-mail, and so on). It adds two more: the date, and the IP address of the access point requesting the PHP file. I’ll add these to the $_POST array.

Here’s the code so far:


$_POST['ip'] = $_SERVER['REMOTE_ADDR']; 
$_POST['date'] = date('M j, Y');
 

Next, we need to copy the $_POST information into a format that our PDF receipt template can use to populate itself dynamically. FDF (Forms Data Format) is the format we need. Adobe created it to represent form data and annotations contained in PDF form. We could use the FDF Toolkit to convert our array into an FDF string, but it’s not available by default on most hosting plans, and for this technique, I prefer a pure PHP solution. Luckily, our FDF needs only a specifically formatted string that contains name-value pairs and a link to an associated PDF file. For these purposes, we can get by without the toolkit.

In FDF, name-value pairs are encased in and separated by parentheses. So, other than dumping the $_POST array contents into a specifically formatted string, we need to make sure that we escape any parentheses a client may have entered. Otherwise, clients may get a vague error message when they attempt to accept the agreement. The simple function “fdf_prep” in the following code block escapes client-submitted information. We’ll run each value through the function before appending it to the $fdf_str string.



function fdf_prep($submitted_value) {
  $search = array('(', ')');
  $replace = array('\(', '\)');
  return str_replace($search, $replace$submitted_value);
}

// the PDF template we created earlier
$pdf_receipt = 'http://example.com/receipt.pdf';

// our FDF string
$fdf_str = "%FDF-1.2\n%����\n"; 
$fdf_str .= "1 0 obj \n<< /FDF "; 
$fdf_str .= "<< /Fields [\n"; 
foreach ($_POST as $key => $val) { 
  $fdf_str .= "<< /V (".fdf_prep($val).")/T ($key)»
>> \n"; 
} 
$fdf_str .= "]\n/F ($pdf_receipt) >>"; 
$fdf_str .= ">>\nendobj\ntrailer\n<<\n"; 
$fdf_str .= "/Root 1 0 R \n\n>>\n"; 
$fdf_str .= "%%EOF";
 

The $fdf_str string now contains each value the client submitted, along with a link to an associated PDF document. Upon opening the file, Acrobat will load the PDF document from the designated location automatically, and use any applicable values embedded in the FDF file to populate it. We don’t have to generate or archive a PDF file for each proposal, we can just store FDF files and generate PDFs as needed. Each FDF variable populates a corresponding input field in the associated PDF with its value—as long as their name attributes match, and a PDF exists at the embedded (yet always editable) location. In general, FDF is a decent way to separate PDF content from presentation.

For record keeping and immediate confirmation, I e-mail myself the generated FDF string as an attachment with an extension of “fdf.” I’ll perform the e-mailing as a function; searching should yield plenty of results on how to send an e-mail attachment using PHP, if you aren’t familiar with how to do it.


$email_status = fdf_email($fdf_str);
 

In the following code block, the first if statement and its else return a receipt only if the aforementioned e-mail was sent successfully. For the HTML acceptance form, we include a hidden field named “submission_source” with a value of “web.” That way, the PHP file “knows” which method the client used to accept the agreement. The second if statement below checks for this. If the “web” form was submitted, the PHP script sends a basic receipt to clients, served as HTML. Otherwise, we can reply with the same FDF file that was e-mailed to me—which would automatically load the PDF receipt template on the client’s device, populated with the same FDF variables.

We use a foreach loop much like the one above with a few modifications to generate HTML receipts for “web” submissions. We want to output each variable other than submission_source to the client—because it might be confusing. As it’s no longer needed, we can unset it, removing it from our $_POST array. Now, inside the loop, we convert the first character of the name portion of each submitted name-value pair to uppercase with PHP’s native ucfirst function. We’ll also convert any underscores into spaces using str_replace. This makes the variable names look like hand-made titles, preparing them for output. Then, we append the titles to the FDF string. Their submitted values follow, but first we’ll convert any applicable characters into HTML entities (&amp; instead of &, for example) using PHP’s native htmlentities function. We’ll use the native stripslashes function to clean up any remaining backslashes.

We use the name of the person who accepted the agreement to personalize the HTML confirmation—based on the input field we created in our HTML acceptance form named “accepters_name.”


if ($email_status) { 
  if ($_POST['submission_source'] != 'web') { 
      header ('Content-Type: application/vnd.fdf'); 
      print $fdf_str; 
    } else { 
      $html_response = "<h1>Acceptance Received</h1>\n»
<p>Thank you, ".$_POST['accepters_name']."! Your acceptance» 
has been received. You may save or print this page» 
as your receipt.</p>\n";
      $html_response .= "<ul>\n";
      unset($_POST['submission_source']);
      foreach($_POST AS $key => $value) { 
        $html_response .= '<li>'.ucfirst(str_replace»
('_', '', $key)).' : '.stripslashes»
(htmlentities($value, ENT_QUOTES))."</li>\n";
      } 
      $html_response .= "</ul>\n";
      echo $html_response; 
    } 
  } else {
    echo "<h1>Error</h1>\n<p>There was an error»
processing your acceptance—please try again or»
e-mail me.</p>\n";
}
 

(Line wraps marked » —Ed.).

It starts with us

Implementing an instantaneous contract agreement helps to get projects off the ground, attract clients on tight timelines, and prevent potential delays. Once you set it up, it saves time and resources for both parties, and also helps to seal the deal. I hope more people will enjoy the simplicity, efficiency, and professionalism of electronically signed agreements. It will start with us, and will initially impress clients, but it won’t be long before clients come to expect an instant, paperless means to accept contracts.

Discuss

Was it good for you, too? Join the discussion »

About the Author

Bjørn Enki Bjørn Enki spends most of his time running Bjørn Enki Website Design, striving for optimal solutions, quality results, and thrilled clients. He lives in Pasadena, CA and is passionate about custom web services, web standards, and open source.