TweetFollow Us on Twitter

Fill Online PDF Forms Using HTML Forms

Volume Number: 20 (2004)
Issue Number: 11
Column Tag: Programming

Fill Online PDF Forms Using HTML Forms

by Sid Steward

Collect data using an HTML form, To deliver a filled-out PDF form that works in Preview

Adobe's Portable Document Format (PDF) is really only as portable as the viewer used to read or print it. This has become an issue in recent years as the Adobe Reader (nee Acrobat Reader) has evolved to support some platforms better than others. Web publishers who desire maximum portability must now take stock: would this work on OS X or Linux as well as Windows? This issue is complicated by the rise of alternative PDF viewers such as Apple's Preview and alternative web browsers such as Konqueror.

Basic PDF viewing and printing is generally okay. Interactive PDF forms, however, are a different story. Adobe Reader on Windows integrates closely with popular web browsers, allowing a web developer to drive an interactive PDF form filling session using the web server (e.g., http://pdfhacks.com/form_session/form_session-1.1/). OS X users, however, won't have the same experience, nor will many Linux users.

One solution is to use HTML form features instead of PDF form features when collecting data. The web server can manage this data collection session, providing data validation and any necessary database access. When the form is complete, the web server can load the PDF form with the user's data, flatten the form, and then serve it to the user. "Flattening" makes the dynamic form data a permanent part of the page, so the resulting PDF will display properly using any PDF viewer.

Collecting data online using HTML forms is old hat. We'll discuss the part where you pack this data into the PDF form for delivery to your user. We'll also talk about how you can automatically convert a PDF form into an HTML form. My free, command-line tool, pdftk, makes both of these possible. We'll need to discuss how to get pdftk working on OS X (it also works on FreeBSD, Linux, Solaris and Windows). We should also touch on PDF forms.

PDF Forms

Using Adobe Acrobat 4, 5, or Acrobat 6.0 Pro (but not 6.0 Standard), you can add interactive form fields to PDF documents. PDF form fields closely resemble the form fields available to HTML form programmers. You have text boxes, check boxes, radio buttons, combo boxes, list boxes, and buttons. These can be further configured to suit your needs. For example, a text box can be configured to be multi-line or to mask password input, and buttons can be configured to submit the form data to a web server.

You can even program PDF forms using JavaScript, although the PDF document object model is quite different than the DOM familiar to web developers. To learn more about programming PDF using JavaScript, see the Acrobat JavaScript Object Specification (http://partners.adobe.com/asn/ developer/pdfs/tn/5186AcroJS.pdf) and the Acrobat JavaScript Scripting Guide (http://partners.adobe. com/asn/acrobat/sdk/public/docs/AcroJSGuide.pdf). We won't discuss using JavaScript with PDF forms, here. Though, I will mention the site http://www.math.uakron.edu/~dpstory/acrotex. html, where you will find JavaScript powered PDF games, such as Tic-Tac-Toe and Naval Battle.

For our purposes, the important thing about PDF forms is that you can permanently merge them with form data. You can do this using Acrobat, or you can use the free, command-line PDF Toolkit, pdftk.

Pdftk, the PDF Toolkit

Pdftk is a command-line program for manipulating PDF documents; it is free software. I created it one year ago to fulfill my own requirements. Since then, I have added features that I believed this free, general-purpose PDF tool should provide. It can:

  • Merge PDF Documents
  • Split PDF Pages into a New Document
  • Decrypt Input as Necessary (Password Required)
  • Encrypt Output as Desired
  • Fill PDF Forms with FDF Data and/or Flatten Forms
  • Apply a Background Watermark
  • Report on PDF Metrics such as Metadata, Bookmarks, and Page Labels
  • Update PDF Metadata
  • Attach Files to PDF Pages or the PDF Document
  • Unpack PDF Attachments
  • Burst a PDF Document into Single Pages
  • Uncompress and Re-Compress Page Streams
  • Repair Corrupted PDF (Where Possible)

The pdftk web site (http://www.pdftk.com) describes these features and explains how to get pdftk working on your system. Pdftk does not require Acrobat or Java. An OS X 10.3 installer is available for pdftk 1.11 from the site. Alternatively, you can build pdftk yourself, a non-trivial task described below. You must have version 1.11 if you want to automatically create an HTML form from a PDF form.

Under pdftk's hood, the iText PDF library does all the heavy lifting. iText is written in Java, but I prefer programming in C++. So I used GCJ, the Java compiler maintained as part of GNU GCC. GCJ allows me to compile iText and then link it with my C++ program. The result is a stand-alone binary that does not need Java. Very cool.

The problem is that your OS X system probably doesn't have GCJ. You must build GCJ (along with GCC) before you can build pdftk on OS X. Happily, John M. Gabriele provides instructions at: http://users.bestweb.net/~john3g/ gcj_osx/gcj_on_osx.html. Brian D. Foy documents his experience building GCJ and pdftk at: http://www.oreillynet.com/pub/wlg/5500.

After building and installing GCC/GCJ, download and unpack the latest version of pdftk (currently 1.11) from http://www.pdftk.com. If you configured GCC/GCJ with --prefix=/usr/local/gcj as John describes, then you won't need to edit the OS X Makefile. Otherwise you will need to edit Makefile.MacOSX so that TOOLPATH matches your location of GCC/GCJ.

After unpacking pdftk 1.11, change into the pdftk-1.11/pdftk directory and run make -f Makefile.MacOSX. It will take awhile to finish compiling. When it is done, move the resulting pdftk program to a convenient location in your $PATH, such as /usr/bin. Test pdftk by displaying its help page:

pdftk --help
and merging a couple PDFs together:
pdftk 1.pdf 2.pdf cat output 12.pdf

Note that you cannot name pdftk's output PDF so it overwrites an input PDF. Also, upon success, pdftk will overwrite files with its output without warning. Change this latter behavior by appending do_ask to the end of the command line, or change the ASK_ABOUT_WARNINGS setting in Makefile.MacOSX and recompile pdftk.

Before we begin using pdftk to fill PDF forms with data, let's talk about FDF.

Store Form Data Using FDF

FDF is Adobe's Forms Data Format, a file format for storing and managing PDF form data. FDF is usually plain text, so you can create it pretty easily using a text editor or your favorite scripting language. FDF is fully documented in section 8.6.6 of the PDF Reference, fourth edition. You can download the latest version of the PDF Reference from: http://partners.adobe.com/asn/tech/ pdf/specifications.jsp. Here is an example of an FDF file that assigns the value "San Francisco" to the PDF field named city:

%FDF-1.2
%aaIO
1 0 obj
<< /FDF << /Fields [	<< /T (city)  /V (San Francisco) >>
                                 << /T (state) /V (California) >> ] >>
>>
endobj
trailer << /Root 1 0 R >>
%%EOF

To simplify FDF creation, I created a PHP program called forge_fdf. It takes form data as name/value pairs and then spins out the matching FDF. The program logic should be easy to reproduce in any language. Visit http://www.pdfhacks.com/forge_fdf/ to download the latest version. In PHP, you would use forge_fdf like so:

<?
require_once( 'forge_fdf.php' );

// use this array for text fields, combo box, and list box form field values
$fdf_data_strings= array( 'city'  => 'San Francisco',
                          'state' => 'California' );

// use this array for check box and radio button values
$fdf_data_names= array();

// these aren't used in this example
$fields_hidden= array();
$fields_readonly= array();

$fdf= forge_fdf(	'',
                        $fdf_data_strings,
                        $fdf_data_names,
                        $fields_hidden,
                        $fields_readonly );

$fdf_fn= tempnam( '.', 'fdf' );
$fp= fopen( $fdf_fn, 'w' );
if( $fp ) {
   fwrite( $fp, $fdf );
   fclose( $fp );

   // serve PDF, but prompt the user to save it to disk
   header( 'Content-type: application/pdf' );
   header(	'Content-disposition: attachment; '.
                'filename=filled_form.pdf' );

   // our pdftk magic; "flatten" merges data with the page
   passthru(   'pdftk form.pdf fill_form '. $fdf_fn.
                                         ' output - flatten' );
	
   unlink( $fdf_fn ); // delete temp file
}
else { // error
   echo 'Error: unable to write temp fdf file: '. $fdf_fn;
}
?>

One FDF peculiarity is that text field, combo box and list box form field values are represented as PDF "strings," where check box and radio button values are represented as PDF "names." For our purposes, names and strings are the same; they are just encoded a little differently in the FDF. That is why forge_fdf takes two arrays of data: fdf_data_strings and fdf_data_names; pack them appropriately. By default, check boxes and radio buttons use the values "Yes" and "Off" to represent their true and false states, respectively. The form designer can choose an alternative to "Yes," but "Off" always means false.

The arrays fields_hidden and fields_readonly have no role in this discussion, so you can ignore them.

Now things are beginning to come together. We have a PDF form, we have an FDF data file, and we can also see, above, that pdftk can merge these two files into a single, non-interactive PDF. Let's talk about that.

PDF Form Filling and Flattening with Pdftk

The pdftk command for filling a PDF form looks like this:

pdftk <input PDF form> fill_form <input FDF data> output <output PDF file> [flatten]

The PDF input, the FDF input, and the PDF output can be a filename, a hyphen (-), or "PROMPT." Passing a hyphen into pdftk instead of an input filename causes pdftk to look for data on stdin. Similarly, passing a hyphen into pdftk instead of an output filename causes pdftk to return data on stdout. You can see we used this latter technique in the snippet, above. Finally, you can pass "PROMPT" into pdftk if you would like pdftk to ask you for the necessary filename at run time.

If you include the flatten output option, then all form field data is converted into static page elements. All of the interactive form features are removed, so the result is a plain old PDF that any viewer can handle. If you omit the flatten option, then form fields are filled to match your input data, but they also remain interactive. You can flatten a PDF form at any time by running:

pdftk filled_form.pdf output flattened_form.pdf flatten

So, these are the back-end pieces to our workaround for online PDF forms. We can take form data, cast it into FDF, merge it with the PDF form, and then serve it to the user. Now let's look into creating the front-end HTML form. To help us along the way, we'll use pdftk to discover PDF form field information.

PDF Form Field Discovery with Pdftk

A PDF form can have dozens of interactive fields. Manually mirroring these fields in HTML would be cumbersome and error-prone. Instead, let's use one of pdftk's reporting features. You can learn everything you need to know about your PDF's interactive form fields by running:

pdftk form.pdf dump_data_fields > form.pdf.fields

This will create an easily parsible plain text report on your form's fields. The output might look like this:

---
FieldType: Text
FieldName: name_last
FieldNameAlt: Last Name
FieldFlags: 8392706
FieldValue:				
FieldJustification: Left
FieldMaxLength: 200
---
FieldType: Button
FieldName: previous1
FieldFlags: 0
FieldJustification: Left
FieldStateOption: Off
FieldStateOption: Yes
---
FieldType: Choice
FieldName: select_one
FieldFlags: 4587520
FieldValue: a
FieldValueDefault: c
FieldStateOption: a
FieldStateOption: b
FieldStateOption: c
---

You can see that the field named title has a maximum length of 200 characters, that a button named previous1 has two possible states: Off and Yes, and a combo box named select_one has three possible states: a, b, and c. Note that push buttons, check boxes and radio buttons all have a FieldType of Button. To tell them apart, you must consult the FieldFlags. Similarly, list boxes and combo boxes both have a FieldType of Choice. See section 8.6 of the PDF Reference for details on field flags and their meanings. We won't be bothering with them, here.

This plain text report should provide you with all the information you need to create an HTML interface to your form. For fun, let's use PHP to do this automatically. Here's a script that reads this text report and generates an HTML form to suit. If you added a "Short Description" to each field in Acrobat, then that text will appear as the FieldNameAlt entry in our report. Our script will use this information, if present, to label the HTML field.

<?php

// this function loads a data file created using pdftk dump_data_fields
function
load_field_data( $field_report_fn )
{
   $ret_val= array();

   $fp= fopen( $field_report_fn, "r" );
   if( $fp ) {
      $line= '';
      $rec= array();
      while( ($line= fgets($fp, 2048))!== FALSE ) {
         $line= rtrim( $line ); // remove trailing whitespace
         if( $line== '---' ) {
            if( 0< count($rec) ) { // end of record
               $ret_val[]= $rec;
               $rec= array();
            }
            continue; // skip to next line
         }

         // split line into name and value
         $data_pos= strpos( $line, ':' );
         $name= substr( $line, 0, $data_pos+ 1 );
         $value= substr( $line, $data_pos+ 2 );

         if( $name== 'FieldStateOption:' ) {
            // pack state options into their own sub-array
            if( !array_key_exists('FieldStateOption:',$rec) ) {
               $rec['FieldStateOption:']= array();
            }
            $rec['FieldStateOption:'][]= $value;
         }
         else {
            $rec[ $name ]= $value;
         }
         }
      if( 0< count($rec)) { // pack final record
         $ret_val[]= $rec;
      }

      fclose( $fp );
   }

   return $ret_val;
}
// open our web page; the form action is a script we provide, below
echo '<html>
<head>
</head>
<body>
<form method="POST" action="pdf_form_fill.php">
<table>';
// create the file form.pdf.fields using pdftk's dump_data_fields
$field_arr= load_field_data( 'form.pdf.fields' );
foreach( $field_arr as $field ) { // iterate form fields
   echo '<tr><td>'; // one row per field
   if(array_key_exists('FieldNameAlt:', $field)) {
      // use human readable name, if available; you can add these in Acrobat
      echo $field['FieldNameAlt:'];
   }
   else {
      echo $field['FieldName:'];
   }
   echo '</td><td>';

   if( $field['FieldType:']== 'Text' ) {
      // construct an HTML text form field to match our PDF text form field;
      // cannot use periods in field names with PHP, so translate them to tildes
      echo   '<input type="text" name="'.
            strtr($field['FieldName:'],'.','~'). '" ';
      // text field default value
      if(array_key_exists('FieldValueDefault:', $field)) {
         echo 'value="'. $field['FieldValueDefault:']. '" ';
      }
      // text field size and maxlength
      if(array_key_exists('FieldMaxLength:', $field)) {
         echo 'maxlength="'. $field['FieldMaxLength:']. '" ';
         if( $field['FieldMaxLength:']< 80 ) {
            echo 'size="'. $field['FieldMaxLength:']. '" ';
         }
         else {
            echo 'size="80" ';
         }
      }
      echo '>';
   }
   else if(array_key_exists('FieldStateOption:', $field)) {
      // use an HTML selection field for all other PDF form fields
      // (check boxes, radio buttons, list boxes, combo boxes);
      // cannot use periods in field names with PHP, so translate them to tildes
      echo   '<select name="'.
            strtr($field['FieldName:'], '.', '~'). '">';
      foreach( $field['FieldStateOption:'] as $option ) {
         echo '<option>'.$option.'</option>';
      }
      echo '</select>';
   }
   echo "</td></tr>\n";
}
// close our table and our HTML page; don't forget the submit button
echo '</table>
<input type="submit" value="Create PDF">
</form>
</body>
</html>';
?>

Now, we need a companion script that takes this submitted data, packs it into the PDF form and serves it to the user. This script is the pdf_form_fill.php action in our above HTML form. It looks much like our earlier form filling example:

<?php
require_once( 'forge_fdf.php' );

$fdf_data_strings= array();
$fdf_data_names= array();

// funny thing; for our purpose, we can get away with packing everything
// everything into fdf_data_strings; that's handy
foreach( $_POST as $key => $value ) {
   // translate tildes back to periods
   $fdf_data_strings[ strtr($key, '~', '.') ]= $value;
}
// ignore these in this example
$fields_hidden= array();
$fields_readonly= array();

$fdf= forge_fdf( '',
                        $fdf_data_strings,
                        $fdf_data_names,
                        $fields_hidden,
                        $fields_readonly );

$fdf_fn= tempnam( '.', 'fdf' );
$fp= fopen( $fdf_fn, 'w' );
if( $fp ) {
   fwrite( $fp, $fdf );
   fclose( $fp );

   header(   'Content-type: application/pdf' );
   header(   'Content-disposition: attachment; '.
             'filename=filled_form.pdf' );

   passthru(   'pdftk form.pdf fill_form '. $fdf_fn.
               ' output - flatten' );
   unlink( $fdf_fn ); // delete temp file
}
else { // error
   echo 'Error: unable to write temp fdf file: '. $fdf_fn;
}
?>

When filling forms this way, it turns out you can pass everything into forge_fdf using the fdf_data_strings array; there's no need to use fdf_data_names. That's handy.

Now the Fun Begins

We have done it! We have created an HTML front-end to filling PDF forms. This is where the fun begins. You can now take everything you know about web programming, such as data validation and database access, and use it to fill PDF forms. Your users will be glad, too, because your resulting PDFs will work in alternative viewers such as Preview, and because you give them a filled-out PDF form for their records (which Adobe Reader does not provide).

To see an online example of these scripts, visit http://www.accesspdf.com/html_pdf_form/. You will also find the code, quoted in this article, available for download.


Sid Steward is a longtime PDF service provider and software developer. He developed the free PDF Toolkit (http://www.AccessPDF.com/pdftk/) and wrote the book PDF Hacks (O'Reilly Media). You can reach him at sid@accesspdf.com.

 
AAPL
$100.96
Apple Inc.
-0.83
MSFT
$47.52
Microsoft Corpora
+0.84
GOOG
$596.08
Google Inc.
+6.81

MacTech Search:
Community Search:

Software Updates via MacUpdate

WhatRoute 1.13.0 - Geographically trace...
WhatRoute is designed to find the names of all the routers an IP packet passes through on its way from your Mac to a destination host. It also measures the round-trip time from your Mac to the... Read more
Chromium 37.0.2062.122 - Fast and stable...
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web. FreeSMUG-Free OpenSource Mac User Group build is... Read more
Attachment Tamer 3.1.14b9 - Take control...
Attachment Tamer gives you control over attachment handling in Apple Mail. It fixes the most annoying Apple Mail flaws, ensures compatibility with other email software, and allows you to set up how... Read more
Duplicate Annihilator 5.0 - Find and del...
Duplicate Annihilator takes on the time-consuming task of comparing the images in your iPhoto library using effective algorithms to make sure that no duplicate escapes. Duplicate Annihilator detects... Read more
jAlbum Pro 12.2 - Organize your digital...
jAlbum Pro has all the features you love in jAlbum, but comes with a commercial license. With jAlbum, you can create gorgeous custom photo galleries for the Web without writing a line of code!... Read more
jAlbum 12.2 - Create custom photo galler...
With jAlbum, you can create gorgeous custom photo galleries for the Web without writing a line of code! Beginner-friendly, with pro results Simply drag and drop photos into groups, choose a design... Read more
Quicken 2015 2.0.4 - Complete personal f...
Quicken 2015 helps you manage all your personal finances in one place, so you can see where you're spending and where you can save. Quicken automatically categorizes your financial transactions,... Read more
iMazing 1.0 - Complete iOS device manage...
iMazing (formerly DiskAid) is the ultimate iOS device manager with capabilities far beyond what iTunes offers. With iMazing and your iOS device (iPhone, iPad, or iPod), you can: Copy music to and... Read more
Xcode 6.0.1 - Integrated development env...
Apple Xcode is Apple Computer's integrated development environment (IDE) for OS X. The full Xcode package is free to ADC members and includes all the tools you need to create, debug, and optimize... Read more
Apple Safari 7.1 - Apple's Web brow...
Apple Safari in OS X Mavericks brings you all-new ways to find and enjoy the best of the web. It works with iCloud to give you a seamless browsing experience across all your devices. It looks out for... Read more

Latest Forum Discussions

See All

View Source – HTML, JavaScript and CSS...
View Source – HTML, JavaScript and CSS 1.0 Device: iOS Universal Category: Utilities Price: $.99, Version: 1.0 (iTunes) Description: View Source is an app plus an iOS 8 Safari extension that makes it easy to do one key web developer... | Read more »
Avenged Sevenfold’s Hail To The King: De...
Avenged Sevenfold’s Hail To The King: Deathbat is Coming to iOS on October 16th Posted by Jessica Fisher on September 19th, 2014 [ permalink ] Just in time for Halloween, on October 16 Avenged Sevenfold will be launching | Read more »
Talisman Has Gone Universal – Can Now be...
Talisman Has Gone Universal – Can Now be Played on the iPhone Posted by Jessica Fisher on September 19th, 2014 [ permalink ] | Read more »
Tap Army Review
Tap Army Review By Jennifer Allen on September 19th, 2014 Our Rating: :: SHOOT EM ALLUniversal App - Designed for iPhone and iPad Mindless but fun, Tap Army is a lane-based shooter that should help you relieve some stress.   | Read more »
Monsters! Volcanoes! Loot! Epic Island f...
Monsters! Volcanoes! Loot! | Read more »
Plunder Pirates: Tips, Tricks, Strategie...
Ahoy There, Seadogs: Interested in knowing our thoughts on all this plundering and pirating? Check out our Plunder Pirates Review! Have you just downloaded the rather enjoyable pirate-em-up Plunder Pirates and are in need of some assistance? Never... | Read more »
Goat Simulator Review
Goat Simulator Review By Lee Hamlet on September 19th, 2014 Our Rating: :: THE GRUFFEST OF BILLY GOATSUniversal App - Designed for iPhone and iPad Unleash chaos as a grumpy goat in this humorous but short-lived casual game.   | Read more »
A New and Improved Wunderlist is Here fo...
A New and Improved Wunderlist is Here for iOS 8 Posted by Jessica Fisher on September 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Evernote Update for iOS 8 Adds Web Clipp...
Evernote Update for iOS 8 Adds Web Clipping, Quick Notes, and More Posted by Ellis Spice on September 19th, 2014 [ permalink ] | Read more »
Apple Names Ultimate Productivity Bundl...
Apple Names Ultimate Productivity Bundle by Readdle as the Essential Bundle on the App Store Posted by Jessica Fisher on September 19th, 2014 [ permalink | Read more »

Price Scanner via MacPrices.net

Mac Pros available for up to $260 off MSRP
Adorama has Mac Pros on sale for up to $260 off MSRP. Shipping is free, and Adorama charges sales tax in NY & NJ only: - 4-core Mac Pro: $2839.99, $160 off MSRP - 6-core Mac Pro: $3739.99, $260... Read more
13-inch 2.6GHz/256GB Retina MacBook Pros avai...
B&H Photo has the 13″ 2.6GHz/256GB Retina MacBook Pro on sale for $1379 including free shipping plus NY sales tax only. Their price is $120 off MSRP. Read more
Previous-generation 15-inch 2.0GHz Retina Mac...
B&H Photo has leftover previous-generation 15″ 2.0GHz Retina MacBook Pros now available for $1599 including free shipping plus NY sales tax only. Their price is $400 off original MSRP. B&H... Read more
21″ 2.7GHz iMac available for $1179, save $12...
Adorama has 21″ 2.7GHz Hawell iMacs on sale for $1179.99 including free shipping. Their price is $120 off MSRP. NY and NJ sales tax only. Read more
iOS 8 Adoption Rate Slower than iOS 7, 6, Hit...
Apple began pushing out iOS 8 updates to eligible devices around 1pm ET on September 17, 2014. However, unlike with iOS 7, which boasted a wide variety of differences from its predecessor iOS 6, in... Read more
LIkely Final Definitive OS X 10.9.5 Mavericks...
Apple has released what will almost certainly be the last incremental version number update of OS X 10.9 Mavericks (save for futire security updates) before OS X 10.10 Yosemite is released next month... Read more
Fingerprints, Apple Pay and Identity Theft Wa...
On Sep 9th, CEO Tim Cook unveiled Apple Pay, along with the new iPhone 6 and iWatch. Apple Pay is a newly developed technology that utilizes a near field communication (NFC) to enable customer... Read more
Amazon Introduces Two All-New Kindles
Amazon on Thursday introduced the 7th generation of its Kindle dedicated e-reader device: Kindle Voyage, its top-of-the-line e-reader, and the new $79 Kindle, with a 20% faster processor, twice the... Read more
Save up to $300 on the price of a new Mac wit...
Purchase a new Mac or iPad at The Apple Store for Education and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free,... Read more
13-inch 2.8GHz Retina MacBook Pro available f...
B&H Photo has the new 2014 13″ 2.8GHz Retina MacBook Pro on sale for $1699.99 including free shipping plus NY sales tax only. They’ll also include free copies of Parallels Desktop and LoJack for... Read more

Jobs Board

Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.