8
Bring Traffic Back With a Mailing List

Findability is more than just getting people to your site. You can convert your new visitors into repeat visitors with a mailing list subscription system.

A mailing list is an exceptionally valuable tool as it allows you to stay in touch with your audience and keep your website on their radar. When you publish new content, update features on your Web app, or just have something to share with your audience, a mailing list is the most direct way to get the word out and generate immediate traffic to your site.

Users who sign up for your mailing list are your superfans. They trust you enough to give you their email address, and enjoy your content so much they’re requesting more via email.

A mailing list is a relationship builder that, if used properly, will cultivate a closer connection between you and your audience. It can turn one-time visitors into repeat visitors, and can get your audience more invested in the content your site provides.

This chapter will introduce some best practices and strategies to help you build your mailing list. It will also teach you how to build an Ajax-powered subscription system that will tie directly into a popular mailing list management Web app to help you manage your list, build email campaigns, and track the success of your messages.

Encouraging Subscriptions

There are a number of factors that can inhibit mailing list subscriptions. Keep these best practices in mind when you present your subscription form to improve your signup rate.

Earn Their Trust

When people sign up for your mailing list they place trust in you that you won’t pester them with spam messages or, worse, sell their email address to those who would. People receive way too much spam email these days to voluntarily put themselves in harm’s way. That’s why it’s imperative that you make it clear to your audience that their email address is safe with you when they subscribe to your mailing list.

To earn your audience’s trust, provide the following reassurance:

Image Provide a reassuring message near the email address field indicating that their email address is safe with you. See FIGURE 8.1.

Figure 8.1 Reassure users that their email addresses will not be abused.

Image

Image Let your audience know they can unsubscribe whenever they like, and provide a link to the unsubscribe page.

Image Let your audience know how frequently you’ll be sending them email, and stick to your word. Sending messages too often might cause a mass exodus from your mailing list, so err on the side of caution.

Image Create a privacy policy page that states that you will never share your audience’s email address, and their email address will be stored on a secure server.

Image Never automatically sign people up for your mailing list. Let them opt in of their own accord.

Users are reluctant to share their email addresses, and rightly so. When you make it clear to your audience that their email addresses are safe with you, you’ll have better luck getting people to subscribe. Of course, it goes without saying that the promises you make to your audience regarding your mailing list must be kept if you hope to maintain a healthy list of subscribers.

Make It Obvious

You don’t want your users to overlook your signup form, so be sure to make it obvious that they have the option. Your subscription form’s location and design are critical to a good signup rate. Make it one of the most prominent elements on your page in order to capture your users’ attention and call them to join the mailing list with a clear heading.

Your home page is a smart place to include the form, and you’ll likely get the best results if you place it in the top third of the page where it will be most visible. There’s no need for blinking images or gaudy colors to capture attention. In fact, this will probably deter subscriptions, as it will look like a sleazy marketing ploy.

Image
Learn to direct a user’s attention by reading “Contrast and Meaning” by Andy Rutledge http://www.alistapart.com/articles/contrastandmeaning

Simply use the power of visual contrast to direct the user’s gaze to the signup form. An accent color, prominent typography, or a unique texture will do the job without making your page look like something from the Las Vegas strip.

Make It Quick

If it looks like it will take too long to sign up for your mailing list users probably won’t bother. Your mailing list should only collect information from the user that’s absolutely essential in order to expedite the signup process.

The simplest subscription form would only ask for an email address. Because it takes so little time to fill out a single field and submit a form, you’re likely to improve your signup rate–especially when the form is placed in a high-traffic place like the home page.

However, it can be advantageous in some situations to request more information from your users. Geographic information such as a home state or zip code or topics the user is interested in can help you send more targeted messages to segments of your mailing list. You could use this information to let people know about an event that is happening near them, or send emails that only contain information of interest to the user.

Be sure to let potential subscribers know why you are requesting this information so they know it can help improve the quality of content they’ll receive. Otherwise, some might be suspicious as to why their zip code is required to receive your emails.

More verbose subscription systems like this may not comfortably fit on a home page, and might need to be placed on a page of their own. You could also take a hybrid approach, providing an email-only subscription form on the home page for speed and a more detailed subscription form on a separate page for users willing to spend a little more time in order to get more targeted messages.

The subscription system that we’ll construct later in this chapter will use Ajax to store subscriptions so no page refresh is required. This will make signing up almost instantaneous.

Tell Them What To Expect and Make It Valuable

You can encourage subscriptions by simply letting your audience know what to expect in your emails. What’s in it for them?

Entice subscriptions by providing content that’s valuable to your audience. Content such as short articles, news, updates about new content on your site, or discounts on products you sell make it worthwhile for users to subscribe to the mailing list.

SitePoint (see FIGURE 8.2) does a brilliant job of providing valuable content in their email newsletters (http://www.sitepoint.com/newsletter/). Each newsletter contains short articles on topics relevant to their audience, along with links to related discussion threads, blog posts, and articles on their site. It works as a miniature digest of their site.

Figure 8.2 SitePoint’s Tech Times email newsletter always includes useful information, which keeps their audience subscribed.

Image

By culling a portion of their newsletter materials from their website they decrease some of the time it takes to author each message, direct loyal readers to the latest content, and make it easy for their audience to stay abreast of their offerings.

Each email message you send is an opportunity for your subscribers to become disenchanted with your mailing list. You can keep your subscribers around by making sure each message contains something of use.

Using a Mailing List Management System

Managing a mailing list has its challenges. You’ll need to store your subscribers’ email addresses securely so they don’t fall into the hands of spammers. You have to provide a convenient way for your audience to unsubscribe from your mailing list. And of course you’ll also need to construct, send, and track your email campaigns. The biggest challenge of building your own mailing list system is handling the incremental email deliveries for large lists, and keeping your server from being blacklisted as a source of spam.

Although it would be possible to tackle these challenges and build all of this functionality from scratch, you’d be reinventing the wheel. Luckily there are some really great mailing list management Web apps that will make all of your mailing list tasks quick and easy.

Why Use a Mailing List Management System?

There are a lot of compelling reasons to use a mailing list management system rather than trying to build your own. Here’s an abbreviated list of some of the functionality at your fingertips when you use an existing system:

Image Secure storage of your list, which will preserve the trust of your subscribers

Image Quick and easy design and development of email campaigns

Image Tracks email opens, clicks, bounces, unsubscribes, and more so you can evaluate the success of each campaign to make the next one even better

Image Automatically cleans your mailing list of invalid or out-of-date addresses when they’re encountered

Image Helps diagnose problems with your message that will get it trapped in spam filters

Image Easy testing of your HTML email in all popular email clients to ensure consistent display

Image Incremental email delivery sends messages one by one so each subscriber’s email address is not seen by other subscribers

Image Scheduled delivery

Image Mailing list segmentation to communicate better with targeted portions of your list

Image Can help keep your mailing list communication compliant with spam laws

Image APIs make it easy to integrate mailing list management system features into your Web apps

Building your own app that does all of this is probably not how you want to spend your time. By using a mailing management system you can stay focused on building your mailing list, and staying in contact with your audience.

It’s free to store your list in a mailing list management system, but sending emails to your subscribers does require payment. The prices are generally very reasonable, and usually get cheaper the more emails you send per campaign.

There are a few mailing list management Web apps to choose from, each offering many of the previously mentioned features. TABLE 8.1 gives you a quick overview of three popular options on the market.

Table 8.1 Mailing List Management Systems Compared

Image

Each of these mailing list management systems provides exceptional functionality and good pricing. All three have an API that makes creating your own subscription forms on your site easy. You could also use a subscription API to integrate mailing list subscriptions into your ecommerce checkout process or any other Web application.

Although a subscription API provides a great deal of flexibility, it’s not required to receive new subscriptions. MailChimp, Campaign Monitor, and Constant Contact will host your signup forms for you if you’re looking for a quick solution. The drawback of hosted forms is that the integration into your site is not quite as seamless.

You can try each system for free first before committing to one. Simply create an account and take each for a spin. You can even create a sample campaign and send it to get a sense for the workflow of each application.

Building an Ajax-Powered Subscription System

The subscription system we’ll build will be flexible enough to be quickly dropped into any page on your site, and will tie directly into a mailing list management system so you can take advantage of the useful features described earlier. Though all three mailing list management systems have their merits, this system will store subscriptions using MailChimp using its handy API. It could easily be adapted to work with any mailing list management system that provides an API.

The subscription form will use Ajax to send email addresses to the server when JavaScript is supported. This eliminates the need for a page refresh, making the signup process exceptionally fast. When JavaScript isn’t supported the system will still be able to store email addresses but will require a page refresh.

Before building the subscription system you’ll first need to set up a free MailChimp account, and create a list to receive your subscriptions.

Monkeying Around with MailChimp

To get started using MailChimp, visit http://mailchimp.com and click the “Free Trial” button to set up an account. It will walk you through a brief setup process, after which you’ll be sent an email with a link to activate your account.

NOTE
In the back of this book you’ll find a special code that will get you a discount on MailChimp’s service so you can check it out without significant investment. New accounts get 30 free credits for test driving purposes.

Once your MailChimp account is active, log in and click the “Lists” tab to create your mailing list (see FIGURE 8.3).

Figure 8.3 In the Lists section of MailChimp, you can create as many managed mailing lists as you like.

Image

Setting Up Your Mailing List

The list setup process is pretty simple. You start by naming the list and providing a default reply-to email address and subject line. You can choose to receive email notifications when users subscribe and unsubscribe if you like.

Next, you’ll need to provide some information about your list that will remind users why they’re receiving your messages, and some contact info in case they want to get in touch. This will help make your list compliant with the United States CAN-SPAM Act, which requires you to include your contact info in every email campaign.

In the next step you can define as many or as few fields as you wish to be included in your subscription form (see FIGURE 8.4). This step is primarily for people who want to host their subscription form on MailChimp and just link to it from their site. We’ll be building our own custom form that will connect to MailChimp using its API, and will only ask for the user’s email address. This will allow the subscription form to be more seamlessly integrated into your site.

Figure 8.4 You can include as many fields in your signup form as you like and even define which are required. Our signup system will only collect an email address, so don’t make any additional fields required.

Image

As mentioned earlier in this chapter, you could create one custom quick signup form that might be placed in a prominent location on your home page, then create a separate subscription page with a more detailed form. If you decide to add additional fields to collect info such as a name and address, be sure the email address is the only one that the user is required to provide. Making additional fields required will cause the quick signup form that only asks for an email address to generate validation errors like “Name was not provided” and “Address was not provided.” The point of the quick signup form is to avoid requiring the user to provide extensive information.

If you have an existing mailing list, you can import it into MailChimp as a tab-delimited text file exported from your database or an Excel spreadsheet. If you don’t have an existing mailing list–which is the case with this example–you can skip this step and start from scratch.

Your list should now be set up and ready to receive subscriptions.

Sign Me Up! The Big Picture of the System

Now that your MailChimp account is all set to receive subscriptions, let’s get a bird’s-eye view of the Ajax subscription system. It will consist of three key components:

1. An HTML form receives the visitor’s email address.

2. JavaScript will listen for the form submission, then make the Ajax call to the server with the email address.

3. PHP on the server will receive the address, check for errors, then store the address in your MailChimp account using their API. A success or error message will be sent back to the HTML page via Ajax to provide user feedback.

To simplify the Ajax coding in our system we’ll use the popular JavaScript framework Prototype (http://www.prototypejs.org/) to listen for an email submission, and handle the Ajax messages. You’ll need to download Prototype before getting started on the subscription system.

The reason that Ajax will be used to store the email address in your mailing list is that it requires no page refresh, which makes the signup process incredibly fast. The progressive enhancement concepts discussed in Chapter 7 will be employed here to make the subscription system work even when JavaScript is disabled or unsupported. When JavaScript isn’t supported the page will have to refresh in order to store the address.

The folks at MailChimp have created a handy API class built with PHP that will make integrating their services into your app pretty easy. You can find the API class, code examples, and documentation of the API at http://mailchimp.com/api/. Be sure to download the API class before getting started.

Create a folder for the project. Inside make a folder called js, and another called inc. Place prototype.js downloaded earlier from http://www.prototypejs.org/ in the js folder. Place the MailChimp API class called MCAPI.class.php in the inc folder.

With all the preliminary setup complete, we can begin development starting with the subscription form.

Creating the Subscription Form

The subscription form is very simple. It has just one field to receive an email address and a button to submit it. As mentioned earlier in this chapter, it’s important to let potential subscribers know that you don’t send spam, or share your mailing list with anyone. Also, give them a quick synopsis of what content they can expect to receive in your emails, and how often they’ll be sent. FIGURE 8.5 shows the signup form we’ll be building.

Figure 8.5 The signup form asks only for an email address

Image

When the form is submitted, user feedback will be displayed adjacent to the email address label where it will be clearly visible. Here’s the HTML for the form marked up with ids so it can be easily styled with CSS and the behavior enhanced with JavaScript:

<p id="description">
      Monthly news and updates plus discounts on all our products.
</p>

<form id="signup" action="<?=$_SERVER['PHP_SELF']?>" method="get">
    <fieldset>
        <legend>Join Our Mailing List</legend>
        <label for="email" id="address-label">Email Address
            <span id="response">
            <? require_once('inc/store-address.php'),
            if($_GET['submit']){ echo storeAddress(); }?>
            </span>
        </label>
        <input type="text" name="email" id="email" />
        <input type="image" src="i/join.jpg" name="submit"
value="Join" alt="Join" />

        <div id="no-spam">We'll never spam or give this address
away</div>
    </fieldset>
</form>

The highlighted code points out a couple areas of interest in the form. The action attribute is populated with the $_SERVER[’PHP_SELF’] superglobal variable to make this form submit to itself. By having PHP write in the name of the page rather than hard coding it, the form will work regardless of the filename of the page to which it is added. This will make it easier to drop into any project.

The second highlighted bit of code is what makes this form work when JavaScript is not supported or is disabled. Inside of the response <span> tag a PHP file that will contain a function called storeAddress() is included into the page. The function is then called and its results are written to the page. This file and its function don’t currently exist, but we’ll create it next.

The storeAddress() function will only run when the form has been submitted. Because the submit button has a name and value attribute it will automatically create a variable called $_GET['submit'] in PHP’s memory when the form is submitted. By looking to see if the variable exists, PHP can determine when to store the address.

This form uses the GET method to transmit the information it gathers to the server. This is because Ajax will be sending information to the server via GET. Keeping the two consistent makes it easier for the PHP script to receive and process the form submission without having to switch between GET and POST methods depending on whether the form was submitted via Ajax or a regular page refresh submission. A consistent submission method keeps things simple.

I’ll skip the CSS for the form here since the primary focus for this example is its functionality. You can download the style sheet used for this example from the companion website at http://buildingfindablewebsites.com.

Building the storeAddress() Function

Before starting the storeAddress() function referenced in the HTML form, create a file for it in the inc folder called store-address.php. This function will perform the following tasks:

1. Validate the email address provided, checking first for an empty submission, and then making sure it appears to be a valid email address.

2. Use the MailChimp API class to save the email address to the mailing list.

3. Return a response to the HTML form indicating an error if the address is invalid or the user is already signed up, or a success message letting the user know they should check their email for a signup confirmation.

There’s one other trick to this function. If JavaScript is not supported it will still be called within the HTML page when the form is submitted, but if Ajax is used to submit the address it will need to be smart enough to run automatically.

Start the function by defining its basic structure and setting up the validation:

function storeAddress(){

    // Validation
    if(!$_GET['email']){ return "No email address provided"; }
    if(!preg_match("/^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-
z0-9-]+)*$/i", $_GET['email'])) {
        return "Email address is invalid";
    }

    // Store subscriptions in MailChimp managed list

}

The first part of the validation is simple. If no email address is provided then it returns a message to let the user know a problem was encountered.

The second validation conditional is a little daunting at first glance. It evaluates the email address provided to see if it looks like a real email address. The long strange string of characters is a regular expression, which was introduced in Chapter 3. In case you missed the earlier explanation, a regular expression searches strings for patterns.

Email addresses follow a very standard pattern that makes them relatively easy to recognize. They start with some letters and numbers followed by an @. More letters and numbers follow, and they wrap up with an extension like .com. This is what the regular expression is looking for, and it will return an error if it doesn’t find it.

Just because the correct pattern is identified doesn’t ensure that it’s a valid email address. Regular expressions can’t sniff out bogus email addresses, just the ones that don’t match the pattern.

Now that the input has been validated, the function needs to send the email address to MailChimp to add it to the mailing list created earlier. We’ll be using MailChimp’s API and their PHP class to tie into the list.

Using this class requires some knowledge of object-oriented programming (OOP), which was discussed briefly in Chapter 4. OOP lets you create discrete, autonomous instances of functionality built from a reusable code block called a class. A class is sort of like the blueprint for these new instances of code—called objects. It defines what the object can do, and what properties it has.

The MailChimp API class will create an object that can perform tasks like add a subscriber or get error/success messages generated from a subscription attempt. The nice thing about using a class is you really don’t have to know what’s going on inside of it; you just have to know how to use it. It’s a bit like driving a car. You may not know how to rebuild the transmission, but you might know how to push the gas pedal and turn the steering wheel.

Before the class can be used it needs to be included into the page. Creating new instances or objects from a class is done using the keyword new. When instantiating the MailChimp class you’ll need to provide your username and password for your account. Replace the highlighted text in the following code example with your credentials.

require_once('MCAPI.class.php'),
$api = new MCAPI('username','password'),

Now that we have created a MailChimp subscriber object, we can use some of its built-in capabilities (called methods) to handle the subscription. Because MailChimp lets you create multiple mailing lists in one account you’ll need to specify to which list you want to add the new subscription. The API has a handy method called lists() that helps you retrieve the list id for each list in your account.

In the following example, the first line of code grabs all lists, which are returned as an array. The second line stores the id of the first list—and in our case the only list—in a variable for use when storing the subscription.

$lists = $api->lists();
$list_id = $lists[0]['id'];

Now that the list id has been retrieved, the email address can be sent to MailChimp using the listSubscribe() method. This method requires three parameters:

1. The list id

2. The email address to be subscribed

3. Additional fields such as the subscriber’s name, address, interest groups, or other information you might have gathered. Because this signup form only asks for an email address, this parameter is left blank.

To check for problems with the signup process the listSubscribe() method is run inside a conditional, which will return a success or error message to provide the user feedback about the process. If a problem is encountered, MailChimp will return a descriptive error message to let the user know what went wrong:

if($api->listSubscribe($list_id, $_GET['email'], '') === true) {
'Success! Check your email to confirm signup.';
}else{
          // An error ocurred, return an error message
           return 'Error: ' . $api->errorMessage;
}

Notice that the success message tells the user to check their email to confirm the subscription. MailChimp automatically sends a confirmation message to the subscriber. This is called a double–opt in process, and it helps prevent accidental or unwanted subscriptions. You can customize the design and language of this email message in your MailChimp admin by navigating to Lists and choosing Customize Designs.

That closes out the function. There is still one small thing that needs to be added to the file outside of the function.

If you recall from the earlier description of the functionality of storeAddress(), I mentioned that the function should be able to run itself automatically when the address is submitted via Ajax. Although Ajax can pass information to the file, it won’t be able to invoke the function without a little help.

After the function, add a very simple conditional that looks for the presence of a GET variable called $_GET['ajax']. This variable will be defined within the URL passed to the store-address.php page from the Ajax script we'll create next. If the variable is set, then the storeAddress() function will run automatically, writing out the response message to the page. The response string will be grabbed by the Ajax script and written into the HTML page inside the response <span> tag.

// If being called via Ajax, autorun the function
if($_GET['ajax']){ echo storeAddress(); }

This one extra line of code lets this script serve the progressively enhanced and JavaScript disabled state of the subscription system. Here’s what the store-address.php file looks like when completed:

<?
function storeAddress(){

      // Validation
      if(!$_GET['email']){ return "No email address provided"; }

      if(!preg_match("/^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-
z0-9-]+)*$/i", $_GET['email'])) {
        return "Email address is invalid";
    }
      require_once('MCAPI.class.php'),
      $api = new MCAPI('username','password'),

      // Fetch mailing list id
      $lists = $api->lists();
      $list_id = $lists[0]['id'];

      if($api->listSubscribe($list_id, $_GET['email'], '') ===
true) {
              // It worked!
              return 'Success! Check your email to confirm signup.';
      }else{
               // An error ocurred, return an error message
               return 'Error: ' . $api->errorMessage;
    }
}
// If being called via Ajax, autorun the function
if($_GET['ajax']){ echo storeAddress(); }
?>

The Ajax Layer

The Ajax layer is the only remaining piece of the subscription system to be completed. It’s made surprisingly simple by the Prototype JavaScript framework, which will help us attach an event to the form, and handle the communication with the server.

When JavaScript is enabled the form shouldn’t actually submit because Ajax will be handling the submission process instead. Prototype will also help out by stopping the form submission event.

To start the construction of the Ajax layer, create a file called mailing-list.js and save it in the js folder.

The script begins by attaching an event to the window object that fires an initialization function when the page has loaded. The initialization function—called init()—attaches an event to the form listening to see if it’s been submitted. When the form is submitted a function called storeAddress() is invoked, which will do all of the Ajax kung fu for us.

Here’s what the basic setup looks like so far:

Event.observe(window, 'load', init, false);

function init(){
        Event.observe('signup','submit',storeAddress);
}

function storeAddress(event) {

}

You might be wondering why the script doesn’t just skip the init() function and instead call storeAddress() directly when the window loads. Better yet, why not just skip the event listener for the window altogether and define the listener for the form immediately?

Because the browser will execute code immediately as it encounters it in a file, attaching an event to the form before the page has loaded would generate an error stating that the form doesn’t exist. The browser can’t attach the form event listener until the whole page has loaded.

The init() function makes this script scalable. It’s not uncommon for modern Web pages to execute a series of JavaScript functions immediately when the page loads to set up the page’s behavior. Using an initialization function allows you to run all sorts of script behaviors simultaneously when the window loads, keeping the script flexible and scalable.

The storeAddress() function is passed a reference to the event that triggers it via a parameter aptly named event. This will be used at the end of the function to disable the form submission.

The storeAddress() function will perform three simple tasks:

1. Update the HTML interface to let the user know their email address is being saved

2. Assemble some variables to be passed to the PHP script then do the Ajax request/response handling

3. Prevent the form from submitting and refreshing the page

Here’s what’s inside the function to make all this happen:

$('response').innerHTML = 'Adding email address…';

var pars = 'ajax=true&email=' + escape($F('email'));
var myAjax = new Ajax.Updater('response', 'inc/store-address.php',
{method: 'get', parameters: pars});

Event.stop(event); // Stop form from submitting when JS is enabled

Prototype has greatly simplified the tasks of this function starting with the way it accesses elements within the HTML document. Prototype lets you replace the verbose document.getElementById('response') with the much more succinct $('response'). This shorthand element access method is used to display user feedback inside <span id="response"> within the subscription form while the Ajax communication is taking place.

The next line assembles two GET variables to be passed to the PHP script. The first one is the $_GET['ajax'] variable referenced at the very end of the store-address.php script outside of the function. Its presence will trigger the PHP script to automatically run its function when Ajax communicates with it.

Another shorthand method is used when grabbing the email address typed into the form. The $F('email') shorthand function accesses the email field and is the same as document.getElementById('email').value. As you can see, the Prototype approach is much shorter. The special characters that might be within the address are encoded using escape() for safe transmission to the PHP script on the server.

Next, Prototype’s Ajax.Updater object is used to send the variables in a query string to the PHP script. It will automatically display the response inside the <span id="response"> tag in the form.

The very last line of the function uses Prototype’s Event.stop() function to prevent the form from submitting. The argument within this function is the one passed earlier to the parent function storeAddress().

Here’s what the mailing-list.js file looks like when fully assembled:

Event.observe(window, 'load', init, false);

function init(){
      Event.observe('signup','submit',storeAddress);
}
function storeAddress(event) {
      // Update user interface
      $('response').innerHTML= 'Adding email address…';
      // Prepare query string and send AJAX request
      var pars = 'ajax=true&email=' + escape($F('email'));
      var myAjax = new Ajax.Updater('response', 'inc/store-address.
php', {method: 'get', parameters: pars});
      Event.stop(event); // Stop form from submitting when JS is
enabled
}

Now that the Ajax layer is complete, all that’s left to finish up the subscription system is to link the form page to the external prototype.js and mailing-list.js scripts. Add the following script tags to the form page, then try it out.

<script typex="text/javascript" src="js/prototype.js"></script>
<script type="text/javascript" src="js/mailing-list.js"></script>

Once you’ve got this subscription system up and running, you should notice that when JavaScript is supported, the Ajax layer makes the signup process almost instantaneous.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset