\section{Sendgrid Tracking}

Using the Sendgrid API and Webhook, maintain a record of all outbound email traffic in the database.

\subsection{Requirements}

\begin{enumerate}
    \item Web route 
    \item Database Table 
    \item Controllers (2)
    \item Model 
    \item View 
    \item Sendgrid Account
    \item Sendgrid Webhook 
\end{enumerate}


\subsection{Web Route}
Add this route to routes/web.php

\begin{lstlisting}[language=PHP]
    Route::post('/sendgrid_tracking', [SendgridTrackingController::class, 'index']);
\end{lstlisting}


\subsection{Database Table} 
This is the sendgrid\_tracking table migration

\begin{lstlisting}[language=PHP]
    Schema::create('sendgrid_tracking', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('email');
            $table->string('subject');
            $table->string('event');
            $table->string('ip')->nullable();
            $table->string('response')->nullable();
            $table->string('send_at')->nullable();
            $table->string('sg_event_id');
            $table->string('sg_message_id');
            $table->string('smtp_id');
            $table->string('timestamp');
            $table->string('tls')->nullable();
            $table->timestamps();
        });
\end{lstlisting}

\subsection{Controllers}
The only required controller is the one which enables collection of email activities. The second one is for displaying the records. 



\subsubsection{SendgridTrackingController}
Used to respond to the push request from Sendgrid webhook.

\begin{lstlisting}[language=PHP]
    public function index(Request $request)
    {
        foreach($request->all() as $d) {
            if(isset($d['smtp-id'])) {
                $d['smtp_id'] = $d['smtp-id'];
                unset($d['smtp-id']);
            }

            SendgridTracking::create($d);
        }
    }
\end{lstlisting}


\subsubsection{SendgridController}
Used to manage view

\begin{lstlisting}[language=PHP]
    public function index() {
        
        $messages = SendgridTracking::orderBy('id', 'desc')->paginate(100);

        return view('admin.sendgrid.index', compact('messages'));
    }
\end{lstlisting}

\subsection{Model}
Supports the database table.

\begin{lstlisting}[language=PHP]

class SendgridTracking extends Model
{
    use HasFactory;
    protected $table = 'sendgrid_tracking';
    protected $fillable = ['email', 'event', 'ip', 'response', 'send_at', 'sg_event_id', 'sg_message_id', 'smtp_id', 'timestamp', 'tls'];
}

\end{lstlisting}


\subsection{View}
Web page to show the list of email activities.

\begin{lstlisting}[language=PHP]

<div class="grid grid-cols-10 p-2 bg-blue-700 text-white rounded-tl-lg rounded-tr-lg">
    <div class="pl-2 col-span-3">Email</div>
    <div class="pl-2 col-span-1">Event</div>
    <div class="pl-2 col-span-2">IP</div>
    <div class="pl-2 col-span-2">Response</div>
    <div class="pl-2 col-span-2">Created At</div>
</div>
<div class="grid grid-cols-10">
    @foreach($messages as $message)
        <div class="text-sm pb-1 pt-1 border-b-2 border-l-2 border-r-2 pl-2 border-gray-300 col-span-3">
            <a class="hover:underline" href="/search?search={{ urlencode($message->email) }}">{{ $message->email }}</a>
        </div>
        @if($message->event == 'deferred' || $message->event == 'bounce')
            <div class="text-sm pb-1 pt-1 border-b-2 border-r-2 pl-2 bg-red-400 border-gray-300 col-span-1">
        @else 
            <div class="text-sm pb-1 pt-1 border-b-2 border-r-2 pl-2 border-gray-300 col-span-1">
        @endif
            {{ $message->event }}
        </div>    
        <div class="text-sm pb-1 pt-1 border-b-2 border-r-2 pl-2 border-gray-300 col-span-2">{{ $message->ip }}</div>    
        <div class="text-sm pb-1 pt-1 border-b-2 border-r-2 pl-2 border-gray-300 col-span-2">{{ substr($message->response,0,20) }}</div>    
        <div class="text-sm pb-1 pt-1 border-b-2 border-r-2 pl-2 border-gray-300 col-span-2">{{ $message->created_at }}</div>    
    @endforeach
</div>
{{$messages->links()}}

\end{lstlisting}

\subsection{Sendgrid Account}
Must establish either a dedicated account or a subuser account. In our case we use subuser accounts of the Westlinks main account.

\subsection{Sendgrid Webhook}
On the Sendgrid subuser account, add a webhook under Mail Settings/Webhook Settings with these settings:

Friendly Name: Sendgrid Tracking 

Post URL: 
\begin{lstlisting}[language=HTML]
https://DOMAINNAME/sendgrid\_tracking
\end{lstlisting}

Under Actions to be posted, select all items 

Engagement data
\begin{itemize}
    \item Opened
    \item Clicked
    \item Unsubscribed
    \item Spam Reports
    \item Group Unsubscribes
    \item Group Resubscribes
\end{itemize}

Deliverability Data
\begin{itemize}
    \item Processed
    \item Dropped
    \item Deferred
    \item Bounced
    \item Delivered
\end{itemize}
    
Turn off Signature Verification

Turn off OAuth Verification 


