Subscribe and unsubscribe system in PHP and AJAX


We post content daily on our website but you know that we can send content or page links to different emails. It sounds good but for that, you will need to create subscribe system. A subscribe system is created to send website page links to all the subscriber's email IDs. It increases page views and website rank. The link can be a blog post link, simple page link, product link, or notification link. 
In this tutorial, we will create subscribe and unsubscribe system in PHP and AJAX. As you know, AJAX is used to execute PHP code without page refreshing. We will create a subscription system using PHP, AJAX, jQuery, bootstrap, and PHP PDO. This is known as the newsletter email subscription system in PHP.


Bootstrap Bootstrap is one of the famous HTML framework. We will create a responsive subscribe form using bootstrap. 
jQueryjQuery is a JS framework that is used to reduce JS code and is easy to read and write. 
PHP PDO - Full form of PDO is PHP Data Objects. PDO is a clean, consistent way to access databases. This means developers can write portable code much easier. It’s very secure without SQL injection. 

Subscribe system in PHP | Sending email using hosting

How to create Subscribe system in PHP and AJAX – 

Everyone knows the advantages of subscribe system. First of all, we will create an MSYQL database table. The table will use to insert all subscriber's email IDs. Email spam is one of the main challenges in the subscribe system but doesn’t worry, we will verify each email by sending a confirmation email.

When a user will enter an email in the text box and click on subscribe button after that an email will deliver to that user's email id and the user will confirm by a link (link with a token key ). We will create a token key and is_verified column in the table. If the user confirms the email id by link then is_verified will be updated to 1 and if the user does not confirm then is_verified will be 0. We can send email notifications by creating a query like a "select email from subscription where is_verified=1". 
Let's create subscribe system in PHP – 
First of all, create an MYSQL database table using the query below- 

CREATE TABLE `subscription` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `email` varchar(200) NOT NULL,
  `token` varchar(355) NOT NULL,
  `is_verified` tinyint(1) NOT NULL DEFAULT 0,
  `created` datetime NOT NULL
) ;

In the table above – 
token – The token will be an automated key. It will use to confirm email or unsubscribe any email. 
is_verified – if email is not confirmed = 0 , if email is confirmed = 1 . (by default 0 at initial time)
As we discussed above, we will insert the user email id into the MYSQL database table. 
Let’s create a PHP PDO connection file – 
config.php 

<?php
define('DBNAME','tute');
define('DBUSER','root');
define('DBPASS','');
define('DBHOST','localhost');
try {
  $db = new PDO("mysql:host=".DBHOST.";dbname=".DBNAME, DBUSER, DBPASS);
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  //echo "Your page is connected with the database successfully..";
} catch(PDOException $e) {
  echo "Issue -> Connection failed: " . $e->getMessage();
}
?>

Kindly set all the constant's values according to your server. 
In this subscribe system, we create an HTML text box and a subscribe button. Now, we will create an index file. The subscribe form will be in the index file. 
index.php 

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title> Subscribe & Unsubscribe system in PHP - Techno Smarter </title>
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
	<link href="style.css" rel="stylesheet">
	<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
	<script src="subscribe_scripts.js"></script>
</head>
<body>
	<div class="container">
 <div class="row">
     <div class="col-sm-3">
     </div>
       <div class="col-sm-6">
      <div class="form-container">
<h2 class="text-center">Subscribe for Latest Updates </h2>
      <p id="msgsub" style="text-align: center;"></p>
      <div id="form_area">
        <form id="userForm" method="POST">
    <input type="text" name="email" id="email" class="form-control"  placeholder="Enter Your Email..">
      <span class="text-danger hidden" id="emailError"></span>
    <br>
    <center><button name="sub_process" class="sub_btn btn btn-primary" id="subscribeButton">Subscribe </button> <img src="loader.gif" height="auto" width="50" id="subloader"></center>
    </form>
    </div>
    </div>
</div>
     <div class="col-sm-3">
         
     </div>
	</div>
</body>
</html>

In the above code, we created a subscribe form using bootstrap CSS classes. The subscribe form will be a responsive form. In the head section, we linked bootstrap(CDN Link), extra stylesheet file, extra subscribe JS file, and jquery (CDN link )file. 
In the next step, we will create AJAX code in a JS file that we already included in the index file. 
subscribe_scripts.js

$(document).on('submit','#userForm',function(e){
        e.preventDefault();
               var regEmail = /^[A-Z0-9._%+-]+@([A-Z0-9-]+\.)+[A-Z]{2,4}$/i;
        var email = $('#email').val();          
           if(email.trim() == '' ) {          
      $('#emailError').text('Please enter email.').removeClass('hidden');
      $('#nameError').text('').addClass('hidden');
            $('#email').focus();
            return false;
        } else if(email.trim() != '' && !regEmail.test(email)) {          
      $('#emailError').text('Please enter a valid email.').removeClass('hidden');
      $('#nameError').text('').addClass('hidden');
            $('#email').focus();
            return false;
        } else {      

        $.ajax({
        method:"POST",
        url: "subscribe.php",
        data:$(this).serialize(),
         beforeSend: function() {
              $("#subloader").show();
           },
        success: function(data){
        $('#msgsub').html(data);
        $("#subloader").hide();
        $('#userForm').find('input').val('');
         $('#form_area').hide();
          
    }});
}
});

In the above code, we used AJAX to send the email value in the PHP file. At the beginning of the script file, we created code lines for email validation and after that AJAX. 
According to this script file, we have to create subscribe PHP file. 
subscribe.php 

 <?php require_once('config.php');
 $email = trim($_POST['email']);
 if(empty($email))
    { 
    echo "Email required";
    }
    else{  
        $sql="SELECT count(*) from subscription where email=:email";
     $stmt = $db->prepare($sql);
    $stmt->bindParam(':email', $email ,PDO::PARAM_STR);
    $stmt->execute();
        $count_email = $stmt->fetchColumn(); 
        if($count_email>0) 
        {
            echo '<div class="msg">You have already subscribed..</div>';
        }
        else 
        {
   $token = bin2hex(random_bytes(50));
            $date = new DateTime(null, new DateTimezone('GMT+1'));
$created=$date->format('Y-m-d H:i:s');
      $sql="INSERT INTO subscription(email,token,created) VALUES(:email,:token,:created)";
       $stmt = $db->prepare($sql);
    $stmt->bindParam(':email', $email ,PDO::PARAM_STR);
    $stmt->bindParam(':token', $token,PDO::PARAM_STR);
       $stmt->bindParam(':created', $created,PDO::PARAM_STR);
   
        $to = $email;
    $subject = "Please confirm your email subscription";
 $FromName='Techno Smarter'; // Your web title
$FromEmail='noreply@technosmarter.com'; // your official web email
$ReplyTo='noreply@technosmarter.com';
$path='https://technosmarter.com/demo/subscribe'; // set your path
 $headers  = "MIME-Version: 1.0\n";
    $headers .= "Content-type: text/html; charset=iso-8859-1\n";
    $headers .= "From: ".$FromName." <".$FromEmail.">\n";
    $headers .= "Reply-To: ".$ReplyTo."\n";
    $headers .= "X-Sender: <".$FromEmail.">\n";
    $headers .= "X-Mailer: PHP\n"; 
    $headers .= "X-Priority: 1\n"; 
    $headers .= "Return-Path: <".$FromEmail.">\n";  
    //message start
     $msgs='<h1 style="text-align:center;">'.$FromName.'</h1> 
     <p style="font-size:16px;text-align:center;">We have received an email confirmation request for subscription. <a href="'.$path.'/verification.php?token='.$token.'">Click Here </a> to confirm your email 
<br><br>
OR
<a target="_blank" href="'.$path.'/unsubscribe.php?token='.$token.'" ><small><u>Unsubscribe </small></u></a>
<br>
All rights are reserved || '.$FromName.'</p>';
    //message end 
       if(@mail($to, $subject, $msgs, $headers,'-f'.$FromEmail))
       {
        $stmt->execute();
     echo '<div class="msg">A verification link has been sent to your email address, please check your email and confirm.<div>'; 
       }
else 
    { 
echo 'The server failed to send the message. Please try again later.'; 
    }
        }
    }
?>

This is one of the major logical PHP file. After the ajax response, the email value comes to this PHP file, and the email inserts into the database. 
First of all, we check whether this email is already available in our database or not. (Email dublicacy restriction)
If the email is not in our database then send a confirmation email to the user and insert the email id into the MYSQL database table. Along with the email id, we insert a unique token key and is_verified 0. 
Kindly set these variable values according to your website in the above code – 

$FromName='Techno Smarter'; // Your web title
$FromEmail='noreply@technosmarter.com'; // your official web email
$ReplyTo='noreply@technosmarter.com';
$path='https://technosmarter.com/demo/subscribe'; // set your path 

From Email – Your website official  id or no reply email like this – info@yoursite.com  or noreply@yoursite.com 
Reply To – Any email. 
Path – A path where your subscribe system source is available. 
As we have already discussed, a confirmation email goes to the user's email id. So that means, we have to create a verification PHP file. 
verification.php 

<?php require_once('config.php'); ?> 
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Verification - Techno Smarter </title>
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
	<link href="style.css" rel="stylesheet">
</head>
<body>
	<div class="container">
 <div class="row">
     <div class="col-sm-3">
     </div>
       <div class="col-sm-6">
      <div class="form-container">
        <?php if(!isset($_GET['token']))
          {
          echo 'Link missing or expired....';
          } 
          else 
          {
            $token=$_GET['token'];
            $sql="SELECT count(*) from subscription where token=:token";
     $stmt = $db->prepare($sql);
    $stmt->bindParam(':token', $token ,PDO::PARAM_STR);
    $stmt->execute();
        $count_token = $stmt->fetchColumn(); 
        if($count_token==0)
        {
       echo 'Link missing or expired....'; 
        }
        else 
        {
       $sql="SELECT count(*) from subscription where token=:token AND is_verified=:status ";
     $stmt = $db->prepare($sql);
       $status=1;
    $stmt->bindParam(':token', $token ,PDO::PARAM_STR);
        $stmt->bindParam(':status', $status ,PDO::PARAM_INT);
    $stmt->execute();
        $count_verification = $stmt->fetchColumn(); 
        if($count_verification>0)
        {
           echo 'You have already subscribed..'; 
        }
        else 
        {
                $sql="UPDATE subscription SET is_verified=:status where token=:token";
     $stmt = $db->prepare($sql);
     $status=1;
    $stmt->bindParam(':token', $token ,PDO::PARAM_STR);
    $stmt->bindParam(':status', $status ,PDO::PARAM_INT);
    $res=$stmt->execute();
    if($res)
    {
      echo '<span style="color:green">You have successfully verified. Now, you will received our latest updates</span>'; 
    }
        }
        }
          }
        ?>

</div>
     <div class="col-sm-3">
      
     </div>
	</div>
</body>
</html>

In the above code, we verify the user email by token key. First of all, we check whether the token key is available or not in our database. If the token id is not available, update the is_verify column value to 0. 
If already confirmed then display the message “ You have already subscribed”. 

Unsubscribe operation in PHP- 

The unsubscribe operation is the opposite of the subscribe operation. As we already sent an unsubscribe link in the confirmation email. A user can unsubscribe after subscribing. 
Let’s create an unsubscribe operation – 
unsubscribe.php 

<?php require_once('config.php'); ?> 
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Unsubscribe - Techno Smarter </title>
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
	<link href="style.css" rel="stylesheet">
</head>
<body>
	<div class="container">
 <div class="row">
     <div class="col-sm-3">
     </div>
       <div class="col-sm-6">
      <div class="form-container">
        <?php if(!isset($_GET['token']))
          {
          echo 'Link missing or expired....';
          } 
          else 
          {
            $token=$_GET['token'];
            $sql="SELECT count(*) from subscription where token=:token";
     $stmt = $db->prepare($sql);
    $stmt->bindParam(':token', $token ,PDO::PARAM_STR);
    $stmt->execute();
        $count_token = $stmt->fetchColumn(); 
        if($count_token==0)
        {
       echo 'Link missing or expired....'; 
        }
        else 
        {
       $sql="SELECT count(*) from subscription where token=:token AND is_verified=:status ";
     $stmt = $db->prepare($sql);
       $status=0;
    $stmt->bindParam(':token', $token ,PDO::PARAM_STR);
        $stmt->bindParam(':status', $status ,PDO::PARAM_INT);
    $stmt->execute();
        $count_verification = $stmt->fetchColumn(); 
        if($count_verification>0)
        {
           echo 'You have already unsubscribed..'; 
        }
        else 
        {
                $sql="UPDATE subscription SET is_verified=:status where token=:token";
     $stmt = $db->prepare($sql);
     $status=0;
    $stmt->bindParam(':token', $token ,PDO::PARAM_STR);
    $stmt->bindParam(':status', $status ,PDO::PARAM_INT);
    $res=$stmt->execute();
    if($res)
    {
      echo '<span style="color:green">You have successfully unsubscribed.</span>'; 
    }
        }
        }
          }
        ?>

</div>
     <div class="col-sm-3">
      
     </div>
	</div>
</body>
</html>

This is very opposite to the email verification operation. In the above code, we created an update operation. The is_verify column value should be 0 or you can delete that column by delete query. 
Like – delete from subscription where token=:token  
Now, we will display all the subscribers in the HTML table. 
This is a CRUD application part. Fetch all the subscribers data and display them in an HTML table. 
subscribers.php 

<?php require_once('config.php'); ?> 
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Subscribers - Techno Smarter </title>
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
	<link href="style.css" rel="stylesheet">
</head>
<body>
	<div class="container">
 <div class="row">
     <div class="col-sm-2">
     </div>
       <div class="col-sm-8">
      <div class="form-container">
        <h1>Subscribers </h1>
        <hr>
        <table class="table table-responsive">
            <th>Email</th>
            <th>Status</th>
            <th>Created</th>
    
        <?php 
    function status($val)
    {
   if($val==1)
   {
 return 'Confirmed'; 
   }
   else 
   {
    return '<span style="color:red;">Pending</span>'; 
   }
    }
            $sql="SELECT count(*) from subscription";
     $stmt = $db->prepare($sql);
    $stmt->execute();
        $count = $stmt->fetchColumn(); 
 if($count==0)
 {
    echo '<tr><td colspan="8">No data available..</td></tr>'; 
 }
 else{
   $sql="SELECT * FROM subscription ORDER BY id DESC"; 
          $stmt=$db->prepare($sql);
            $stmt->execute();
$rows=$stmt->fetchAll();
foreach($rows as $row)
{
    echo '<tr>
    <td>'.$row['email'].'</td>
    <td>'.status($row['is_verified']).'</td>
      <td>'.$row['created'].'</td>
    </tr> '; 
}
}
        ?> 
            </table>

</div>
     <div class="col-sm-2">
      
     </div>
	</div>
</body>
</html>

You can check all subscriber's emails with status (pending or confirmed ) on this page. 
Now, let’s design the subscribe form. As you have already seen, we included style.css in the index.php file. 
If you want to design a subscribe form then create a CSS file.
style.css 

		body{
            background: #f0f0f1;
        }
        #subloader{
			display: none;
		}
		.form-container
 {
 box-shadow: -5px 0px 15px -3px rgba(0,0,0,0.1);
   padding: 20px;
    border-radius: 20px;
    background-color: #fff;
    margin-top: 10px ;
}
    input{
    padding: 10px 20px;
    color: #1E266D;
    width: 100%;
    height: 50px;
    background: #F5FAFF !important;
    border: 1px solid #EEF1FF;
    border-radius: 5px;
}
.sub_btn{
padding: 11px 25px;
    font-size: 13px;
    font-weight: 500;
    text-transform: uppercase;
    color: #fff;
    background-color: #d72924;
    border-style: none;
    border-radius: 0 0 0 0;
    box-shadow: 0 1px 100px 0 #ea0d0d inset;
}

Note 1- Please download a loader gif image and save it as loader.gif in the same folder. 
Note 2 – Kindly run this code on your liver server because the mail() function does not work on the local server. 
Tip – If you want to send an email notification to all confirmed subscriber's emails while creating a post or page- 
1.    First of all, fetch all the emails and token id where is_verified=1 

Send email to subscribers - 

A subscribe system cannot be completed by sending emails to all subscribers who already confirmed their email id. Here, we will create a form with two fields. The first field, you can use for the post title, subject or notification title, etc, and the second field, you can use for pot content, offers content, or any notification. We will same mail() function to send emails to all subscribers. 

send.php

<?php require_once('config.php'); ?> 
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Send Email Notifications to subscribers - Techno Smarter </title>
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
	<link href="style.css" rel="stylesheet">
	<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
	<script src="subscribe_scripts.js"></script>
</head>
<body>
	<div class="container">
 <div class="row">
     <div class="col-sm-3">
     </div>
       <div class="col-sm-6">
      <div class="form-container">
<h2 class="text-center">Send Email to Subscribers </h2>
<?php 
  if(isset($_POST['send']))
  {
    $title=trim($_POST['title']); 
    $content=trim($_POST['content']);
 $FromName='Techno Smarter'; // Your web title
$FromEmail='noreply@technosmarter.com'; // your official web email
$ReplyTo='noreply@technosmarter.com';
$path='https://technosmarter.com/demo/subscribe'; // set your path
 $headers  = "MIME-Version: 1.0\n";
    $headers .= "Content-type: text/html; charset=iso-8859-1\n";
    $headers .= "From: ".$FromName." <".$FromEmail.">\n";
    $headers .= "Reply-To: ".$ReplyTo."\n";
    $headers .= "X-Sender: <".$FromEmail.">\n";
    $headers .= "X-Mailer: PHP\n"; 
    $headers .= "X-Priority: 1\n"; 
    $headers .= "Return-Path: <".$FromEmail.">\n";  
    //message start
     
    //message end 

   $sql="SELECT token,email FROM subscription WHERE is_verified=:status"; 
   $stmt = $db->prepare($sql);
   $status=1;
    $stmt->bindParam(':status', $status ,PDO::PARAM_STR);
            $stmt->execute();
$rows=$stmt->fetchAll();
foreach($rows as $row)
{
      $to=$row['email'];
      $token=$row['token'];
         $subject=$title.' ref '.rand(999,100);
    $msgs='<h1 style="text-align:center;">'.$FromName.'</h1> 
     <p style="font-size:16px;text-align:center;"><strong>'.$title.'</strong><br>'.$content.'
<br><br><br> 
<a target="_blank" href="'.$path.'/unsubscribe.php?token='.$token.'" ><small><u>Unsubscribe </small></u></a>
<br>
All rights are reserved || '.$FromName.'</p>';

if(@mail($to, $subject, $msgs, $headers,'-f'.$FromEmail))
      {
       $success=1;
      }
else 
    { 
echo 'The server failed to send the message. Please try again later.'; 
    }
}
       if(isset($success))
       {
           echo '<div class="msg">The email has been sent...<div>'; 
       }
  }
  ?>
        <form action="" method="POST">
          <div class="row">
            <div class="col-sm-12">
            <div class="form-group"><input type="text" name="title" class="form-control"  placeholder="Enter Title" required></div>
          </div>
          </div>
          <br> 
           <div class="row">
             <div class="col-sm-12">
            <div class="form-group">
              <textarea name="content" class="form-control" placeholder="Your content.." rows="7" required></textarea>
              <br>
            </div>
          </div>
    <center><button name="send" class="sub_btn btn btn-primary">Send </button></center>
    </form>
    </div>
</div>
     <div class="col-sm-3">
         
     </div>
	</div>
</body>
</html>

Subscribe system in PHP | Sending email using hosting

2. Use the mail() function to send emails or PHPMailer (How to send email using PHPMailer and Host SMTP). 
3. Must include the unsubscribe link in your email template. You can check the unsubscribe link in the verification template. 


Please Share

Recommended Posts:-