Generate a unique process_id for each sending of emails.
Only use if process_id is given to setup a 1x1 tracking pixel to record
if email was opened.
 define('GLM_MEMBERS_MESSAGES_PLUGIN_VERSION', '0.0.1');
 
 // DB Version
-define('GLM_MEMBERS_MESSAGES_PLUGIN_DB_VERSION', '0.0.5');
+define('GLM_MEMBERS_MESSAGES_PLUGIN_DB_VERSION', '0.0.6');
 
 // This is the minimum version of the GLM Members DB plugin require for this plugin.
 define('GLM_MEMBERS_MESSAGES_PLUGIN_MIN_MEMBERS_REQUIRED_VERSION', '2.8.0');
 
 
     public $ajaxSide = true;
 
-    public function __construct ($wpdb, $config)
+    public function __construct ( $wpdb, $config )
     {
 
         // Save WordPress Database object
 
             'content'      => $emailContent,
             'footer'       => $message['footer'],
             'templateName' => $message['title'],
+            'process_id'   => false,
+            'email'        => false,
         );
 
         // Load Smarty Template support
 
--- /dev/null
+<?php
+
+/**
+ * Gaslight Media Members Database
+ * PDF Output by admin-ajax
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @version  0.1
+ */
+
+/**
+ * Steve Note
+ *
+ * You can get to this using the following URL.
+ *
+ *
+ {host}/wp-admin/admin-ajax.php?action=glm_members_admin_ajax&glm_action=runQueue
+ *
+ * You should be able to do this as POST or GET and should be able to add and read additional parameters.
+ * I added a "mystuff" parameter to the URL above and it does output from the code in the
+ * modelAction() function below.
+ *
+ * To add another model under models/admin/ajax all you need to do is create it and add it to the
+ * setup/validActions.php file.
+ *
+ */
+
+/**
+ * This class handles the work of creating new invoices based on.
+ * 1) Member Type of member matching a paid invoiceType
+ * 2) Member renewal date past
+ * 3) Member has Billing Account
+ * 4) Member has no active Invoice
+ * 5) Renewal date is within the next 30 Days
+ *
+ */
+class GlmMembersAdmin_ajax_trackMessagePixel
+{
+
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * Plugin Configuration Data
+     *
+     * @var $config
+     * @access public
+     */
+    public $config;
+
+    public $ajaxSide = true;
+
+    public function __construct ( $wpdb, $config )
+    {
+
+        // Save WordPress Database object
+        $this->wpdb = $wpdb;
+
+        // Save plugin configuration object
+        $this->config = $config;
+
+        // parent::__construct( $this->wpdb, $this->config );
+
+    }
+
+    /**
+     * Perform Model Action
+     *
+     * This method does the work for this model and returns any resulting data
+     *
+     * @return array Status and data array
+     *
+     * 'status'
+     *
+     * True if successfull and false if there was a fatal failure.
+     *
+     * 'menuItemRedirect'
+     *
+     * If not false, provides a menu item the controller should
+     * execute after this one. Normally if this is used, there would also be a
+     * modelRedirect value supplied as well.
+     *
+     * 'modelRedirect'
+     *
+     * If not false, provides an action the controller should execute after
+     * this one.
+     *
+     * 'view'
+     *
+     * A suggested view name that the contoller should use instead of the
+     * default view for this model or false to indicate that the default view
+     * should be used.
+     *
+     * 'data'
+     *
+     * Data that the model is returning for use in merging with the view to
+     * produce output.
+     *
+     */
+    public function modelAction ( $actionData = false )
+    {
+
+        if ( isset( $_REQUEST['process_id'] ) && isset( $_REQUEST['email'] ) ) {
+            $email      = filter_var( $_REQUEST['email'], FILTER_VALIDATE_EMAIL );
+            $process_id = filter_var( $_REQUEST['process_id'], FILTER_SANITIZE_STRING );
+
+            echo '<pre>$email: ' . print_r( $email, true ) . '</pre>';
+
+            echo '<pre>$process_id: ' . print_r( $process_id, true ) . '</pre>';
+
+            $this->wpdb->update(
+                GLM_MEMBERS_MESSAGES_PLUGIN_DB_PREFIX . 'email_logs',
+                array( 'email_read' => true, 'read_date' => date( 'Y-m-d H:i:s' ) ),
+                array( 'to_email'   => $email, 'process_id' => $process_id ),
+                array( '%s', '%s' ),
+                array( '%s', '%s' )
+            );
+        }
+
+        $return = array(
+            true
+        );
+
+        // echo json_encode( $return, true );
+        echo true;
+        return;
+
+    }
+
+
+}
 
         $fromName     = $message['from_name'];
         $replyToEmail = $message['reply_to_email'];
         $subject      = $message['subject'];
+        $process_id   = sha1( $messageId . '-' . date( 'Y-m-d H:i:s' ) );
 
         if ( $messageId && $message && is_array( $data ) && !empty( $data ) ) {
             foreach ( $data as $memData ) {
                                 'mobile_phone' => $contact['mobile_phone'],
                             )
                         );
-                        $messageBody = $this->generateHTML( $emailData, wpautop( $message['message_body'] ), $message );
+                        $messageBody = $this->generateHTML( $emailData, wpautop( $message['message_body'] ), $message, $process_id, $contact['email'] );
 
                         // Add this to the email_queue
                         $this->wpdb->insert(
                                 'message_body'   => $messageBody,
                                 'queue_date'     => date( 'Y-m-d H:i:s' ),
                                 'processed'      => false,
+                                'process_id'     => $process_id,
                             ),
                             array(
                                 '%d', // message_id
                                 '%s', // message_body
                                 '%s', // queue_date
                                 '%s', // processed
+                                '%s', // process_id
                             )
                         );
                     }
      * @access public
      * @return void
      */
-    function generateHTML( $data, $view, $message )
+    function generateHTML( $data, $view, $message, $process_id, $email )
     {
 
         // Load Smarty Template support.
             'content'      => $emailContent,
             'footer'       => $message['footer'],
             'templateName' => $message['title'],
+            'process_id'   => $process_id,
+            'email'        => $email,
         );
         if ( is_array( $tData ) && count( $tData ) > 0 ) {
             foreach ( $tData as $k => $d ) {
 
                             'reply_to_email' => $email['reply_to_email'],
                             'message_body'   => '',
                             'send_date'      => date( 'Y-m-d H:i:s' ),
+                            'process_id'     => $email['process_id'],
                         ),
                         array(
                             '%d',
                             '%s',
                             '%s',
                             '%s',
+                            '%s',
                         )
                     );
                 }
 
+++ /dev/null
--- Gaslight Media Members Database
--- File Created: 5/24/19
--- Database Version: 0.0.5
--- Database Creation Script - Messages Add-On
---
--- To permit each query below to be executed separately,
--- all queries must be separated by a line with four dashes
-
--- email_messages
-CREATE TABLE {prefix}email_messages (
-    id INT NOT NULL AUTO_INCREMENT,
-    template_id INT NOT NULL,
-    title TINYTEXT NULL,
-    image TINYTEXT NULL,
-    archived BOOLEAN DEFAULT false,
-    from_email TINYTEXT NOT NULL,
-    from_name TINYTEXT NULL,
-    reply_to_email TINYTEXT NULL,
-    subject TINYTEXT NOT NULL,
-    last_updated DATETIME NOT NULL,
-    message_body TEXT NOT NULL,
-    footer TEXT NULL,
-    PRIMARY KEY (id)
-);
-
-----
-
--- Logs
-CREATE TABLE {prefix}email_logs (
-    id INT NOT NULL AUTO_INCREMENT,
-    message_id INT NOT NULL,
-    to_email TINYTEXT NOT NULL,
-    subject TINYTEXT NOT NULL,
-    from_email TINYTEXT NOT NULL,
-    reply_to_email TINYTEXT NULL,
-    message_body TEXT NOT NULL,
-    send_date DATETIME NOT NULL,
-    email_read BOOLEAN DEFAULT false,
-    read_date DATETIME NULL,
-    PRIMARY KEY (id)
-);
-
-----
-
--- Queue
-CREATE TABLE {prefix}email_queue (
-    id INT NOT NULL AUTO_INCREMENT,
-    message_id INT NOT NULL,
-    to_email TINYTEXT NOT NULL,
-    subject TINYTEXT NOT NULL,
-    from_email TINYTEXT NOT NULL,
-    reply_to_email TINYTEXT NULL,
-    message_body TEXT NOT NULL,
-    queue_date DATETIME NOT NULL,
-    processed BOOLEAN DEFAULT false,
-    PRIMARY KEY (id)
-);
-
-----
-
--- Template
-CREATE TABLE {prefix}email_templates (
-    id INT NOT NULL AUTO_INCREMENT,
-    name TEXT NOT NULL,
-    image TINYTEXT NULL,
-    footer TEXT NULL,
-    PRIMARY KEY (id)
-);
 
--- /dev/null
+-- Gaslight Media Members Database
+-- File Created: 5/24/19
+-- Database Version: 0.0.6
+-- Database Creation Script - Messages Add-On
+--
+-- To permit each query below to be executed separately,
+-- all queries must be separated by a line with four dashes
+
+-- email_messages
+CREATE TABLE {prefix}email_messages (
+    id INT NOT NULL AUTO_INCREMENT,
+    template_id INT NOT NULL,
+    title TINYTEXT NULL,
+    image TINYTEXT NULL,
+    archived BOOLEAN DEFAULT false,
+    from_email TINYTEXT NOT NULL,
+    from_name TINYTEXT NULL,
+    reply_to_email TINYTEXT NULL,
+    subject TINYTEXT NOT NULL,
+    last_updated DATETIME NOT NULL,
+    message_body TEXT NOT NULL,
+    footer TEXT NULL,
+    PRIMARY KEY (id)
+);
+
+----
+
+-- Logs
+CREATE TABLE {prefix}email_logs (
+    id INT NOT NULL AUTO_INCREMENT,
+    message_id INT NOT NULL,
+    to_email TINYTEXT NOT NULL,
+    subject TINYTEXT NOT NULL,
+    from_email TINYTEXT NOT NULL,
+    reply_to_email TINYTEXT NULL,
+    message_body TEXT NOT NULL,
+    send_date DATETIME NOT NULL,
+    email_read BOOLEAN DEFAULT false,
+    read_date DATETIME NULL,
+    process_id TINYTEXT NOT NULL,
+    PRIMARY KEY (id)
+);
+
+----
+
+-- Queue
+CREATE TABLE {prefix}email_queue (
+    id INT NOT NULL AUTO_INCREMENT,
+    message_id INT NOT NULL,
+    to_email TINYTEXT NOT NULL,
+    subject TINYTEXT NOT NULL,
+    from_email TINYTEXT NOT NULL,
+    reply_to_email TINYTEXT NULL,
+    message_body TEXT NOT NULL,
+    queue_date DATETIME NOT NULL,
+    processed BOOLEAN DEFAULT false,
+    process_id TINYTEXT NOT NULL,
+    PRIMARY KEY (id)
+);
+
+----
+
+-- Template
+CREATE TABLE {prefix}email_templates (
+    id INT NOT NULL AUTO_INCREMENT,
+    name TEXT NOT NULL,
+    image TINYTEXT NULL,
+    footer TEXT NULL,
+    PRIMARY KEY (id)
+);
 
     '0.0.3' => array('version' => '0.0.3', 'tables' => 4, 'date' => '06/04/2019'),
     '0.0.4' => array('version' => '0.0.4', 'tables' => 4, 'date' => '06/07/2019'),
     '0.0.5' => array('version' => '0.0.5', 'tables' => 4, 'date' => '08/14/2019'),
+    '0.0.6' => array('version' => '0.0.6', 'tables' => 4, 'date' => '08/16/2019'),
 );
 
 
--- /dev/null
+-- Gaslight Media Members Database  - Messages Add-On
+-- File Created: 8/16/2019
+-- Database Version: 0.0.6
+-- Database Update From Previous Version Script
+--
+-- To permit each query below to be executed separately,
+-- all queries must be separated by a line with four dashes
+
+-- Add process_id to email_queue
+ALTER TABLE {prefix}email_queue ADD COLUMN process_id TINYTEXT NOT NULL;
+
+----
+
+-- Add process_id to email_logs
+ALTER TABLE {prefix}email_logs ADD COLUMN process_id TINYTEXT NOT NULL;
 
         'ajax' => array(
             'newsletter'         => GLM_MEMBERS_MESSAGES_PLUGIN_SLUG,
             'ajaxMessagePreview' => GLM_MEMBERS_MESSAGES_PLUGIN_SLUG,
+            'trackMessagePixel'  => GLM_MEMBERS_MESSAGES_PLUGIN_SLUG,
         ),
         'messages' => array(
             'index'              => GLM_MEMBERS_MESSAGES_PLUGIN_SLUG,
 
     </fieldset>
 
     <fieldset class="fieldset cell small-12 medium-6">
-        <legend>Message Options</legend>
+        <legend>Message Configuration</legend>
 
         {* Template
         {$ui = [
 
     {/literal}
   </head>
   <body style="-moz-box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-box-sizing:border-box;-webkit-text-size-adjust:100%;Margin:0;background:#f3f3f3!important;box-sizing:border-box;color:#0a0a0a;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;min-width:100%;padding:0;text-align:left;width:100%!important">
-    <span class="preheader" style="color:#f3f3f3;display:none!important;font-size:1px;line-height:1px;max-height:0;max-width:0;mso-hide:all!important;opacity:0;overflow:hidden;visibility:hidden"></span>
+    <span class="preheader" style="color:#f3f3f3;display:none!important;font-size:1px;line-height:1px;max-height:0;max-width:0;mso-hide:all!important;opacity:0;overflow:hidden;visibility:hidden">{if !empty($process_id)}<img style="display:none!important;width:1px;height:1px;visibility:hidden;" src="{$ajaxUrl}?action=glm_members_admin_ajax&glm_action=trackMessagePixel&process_id={$process_id}&email={$email}">{/if}</span>
     <table class="body" style="Margin:0;background:#f3f3f3!important;border-collapse:collapse;border-spacing:0;color:#0a0a0a;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;height:100%;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;width:100%">
       <tr style="padding:0;text-align:left;vertical-align:top">
         <td class="center" align="center" valign="top" style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">