<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Itay Eylath</title>
    <description>The latest articles on Forem by Itay Eylath (@itayeylath).</description>
    <link>https://forem.com/itayeylath</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1362189%2F75399852-138e-46be-9d34-56bbc13c4e24.jpeg</url>
      <title>Forem: Itay Eylath</title>
      <link>https://forem.com/itayeylath</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/itayeylath"/>
    <language>en</language>
    <item>
      <title>From Metrics to Action: Turning Embedding Analysis into Sprint Tickets</title>
      <dc:creator>Itay Eylath</dc:creator>
      <pubDate>Mon, 23 Feb 2026 09:04:38 +0000</pubDate>
      <link>https://forem.com/itayeylath/from-metrics-to-action-turning-embedding-analysis-into-sprint-tickets-4jgl</link>
      <guid>https://forem.com/itayeylath/from-metrics-to-action-turning-embedding-analysis-into-sprint-tickets-4jgl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo76z2zfz56wku0jrqwm2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo76z2zfz56wku0jrqwm2.png" alt=" " width="278" height="126"&gt;&lt;/a&gt;&lt;br&gt;
In an agile Computer Vision startup, &lt;strong&gt;global accuracy is a vanity metric&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It tells you the model is working.&lt;/p&gt;

&lt;p&gt;It doesn’t tell you what to fix next.&lt;/p&gt;

&lt;p&gt;To move fast, you need &lt;strong&gt;actionable signals&lt;/strong&gt; not dashboards.&lt;/p&gt;

&lt;p&gt;Here’s how we transform raw embeddings into sprint ready decisions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70ds9l43sutoe7bjrh1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70ds9l43sutoe7bjrh1g.png" alt=" " width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;1. Stop Calculating Accuracy. Start Finding Confusion.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A single accuracy score hides local failures.&lt;/p&gt;

&lt;p&gt;Instead of asking &lt;em&gt;“How accurate is the model?”&lt;/em&gt;, ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Where exactly is the model failing?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We use &lt;strong&gt;1-Nearest Neighbor (1-NN)&lt;/strong&gt; evaluation to expose structural confusion between visually similar items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import numpy as np
from sklearn.metrics import pairwise_distances

# Compute pairwise distances between embeddings
D = pairwise_distances(embeddings, metric="euclidean")

# Ignore self comparisons
np.fill_diagonal(D, np.inf)

# Identify closest neighbor
closest_idx = np.argmin(D, axis=1)
is_correct = labels == labels[closest_idx]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of celebrating 88% accuracy, we extract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Which classes are confused&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How often confusion happens&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whether errors are isolated or concentrated&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This immediately narrows the problem space.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. Margin: Measuring Model Uncertainty&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Accuracy is binary.&lt;/p&gt;

&lt;p&gt;Confidence is continuous.&lt;/p&gt;

&lt;p&gt;We define &lt;strong&gt;Margin&lt;/strong&gt; as the gap between the closest and second closest neighbors:&lt;/p&gt;

&lt;p&gt;Margin = Dist_{2nd} - Dist_{1st}&lt;/p&gt;

&lt;p&gt;If the margin is near zero, the model is effectively guessing between two nearly identical items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Sort distances per sample
sorted_dists = np.sort(D, axis=1)

# Compute margin
margin = sorted_dists[:, 1] - sorted_dists[:, 0]

# Flag unstable samples
low_confidence = margin &amp;lt; 0.05
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Low margin samples are early warning signals.&lt;/p&gt;

&lt;p&gt;They tell you where instability lives before accuracy visibly drops.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Visualization for Intuition (Not Decisions)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Metrics drive action.&lt;/p&gt;

&lt;p&gt;Visualization builds intuition.&lt;/p&gt;

&lt;p&gt;We use PCA or t-SNE to project embeddings into 2D space:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from sklearn.manifold import TSNE

tsne_results = TSNE(
    n_components=2,
    perplexity=30,
    random_state=42
).fit_transform(embeddings)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overlapping clusters often explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Why two classes are confused&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whether boundaries are weak&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whether the representation itself lacks separation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Visualization doesn’t replace metrics it explains them.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. The Operational Matrix: Converting Signals to Ownership&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Analysis only matters if someone owns the fix.&lt;/p&gt;

&lt;p&gt;We translate technical signals into clear action items:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Signal&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Meaning&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Action Item&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Owner&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;High Intra-class Distance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same class samples are visually inconsistent&lt;/td&gt;
&lt;td&gt;Clean dataset (remove low-quality samples)&lt;/td&gt;
&lt;td&gt;Data Ops&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Strong Confusion Pair&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Two distinct classes overlap heavily&lt;/td&gt;
&lt;td&gt;Add discriminative features or review labeling&lt;/td&gt;
&lt;td&gt;CV / Product&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Low Margin Cluster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Category boundary is unstable&lt;/td&gt;
&lt;td&gt;Targeted data collection or fine-tuning&lt;/td&gt;
&lt;td&gt;ML Team&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is where evaluation becomes execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;5. The Agile Loop&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Every iteration follows the same structure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Run embedding evaluation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extract top confusion pairs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rank unstable classes by margin&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convert top issues into sprint tickets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Re-run metrics after fixes&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Metrics → Ownership → Action → Re-measure&lt;/p&gt;

&lt;p&gt;No guesswork.&lt;/p&gt;

&lt;p&gt;No intuition battles.&lt;/p&gt;

&lt;p&gt;No blind retraining.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What We Learned&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Most persistent errors were structural, not architectural.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Margin was a better early warning signal than accuracy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Concentrated confusion mattered more than global percentage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ownership accelerated improvement more than model complexity.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest shift wasn’t technical.&lt;/p&gt;

&lt;p&gt;It was operational.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Bottom Line&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In real world Computer Vision systems, the difference between stable and unstable performance isn’t a new architecture.&lt;/p&gt;

&lt;p&gt;It’s a tighter feedback loop.&lt;/p&gt;

&lt;p&gt;If a metric doesn’t lead to a sprint ticket, it’s just noise.&lt;/p&gt;

&lt;p&gt;The best models aren’t the ones with the highest accuracy.&lt;/p&gt;

&lt;p&gt;They’re the ones whose failures are measurable, owned, and shrinking every iteration.&lt;/p&gt;

&lt;p&gt;This project is open source feel free to explore the code on GitHub and try it yourself:&lt;br&gt;
&lt;a href="https://github.com/itayeylath/metrics-to-actions" rel="noopener noreferrer"&gt;https://github.com/itayeylath/metrics-to-actions&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>productivity</category>
      <category>startup</category>
    </item>
    <item>
      <title>A Simple Docker Cleanup Script to Save Your Day</title>
      <dc:creator>Itay Eylath</dc:creator>
      <pubDate>Mon, 15 Jul 2024 11:56:28 +0000</pubDate>
      <link>https://forem.com/itayeylath/a-simple-docker-cleanup-script-to-save-your-day-4n28</link>
      <guid>https://forem.com/itayeylath/a-simple-docker-cleanup-script-to-save-your-day-4n28</guid>
      <description>&lt;p&gt;Are you tired of dealing with cluttered Docker containers? 🐳&lt;br&gt;
Or any issues as a Linux user? 🛠️&lt;br&gt;
Or maybe, you are just a lazy FullStack developer? 🥱&lt;/p&gt;

&lt;p&gt;If you find your development environment getting messy with containers that you no longer need, I have a nifty little script that will solve your Docker woes in no time :-)&lt;/p&gt;
&lt;h2&gt;
  
  
  The Magic Script: 🪄
&lt;/h2&gt;

&lt;p&gt;Let me introduce you to &lt;code&gt;docker-cleanup.sh&lt;/code&gt; - a simple yet powerful script that will give your Docker environment a fresh start &lt;/p&gt;

&lt;p&gt;Here's what the script looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Check if there are any containers
if docker ps -a &amp;amp;&amp;gt; /dev/null; then
    echo "Removing existing containers..."
    # Remove all containers
    docker rm -f $(docker ps -a -q)
    # Restart Docker
    echo "Restarting Docker..."
    sudo systemctl restart docker
    # Print Docker status
    echo "Docker status:"
    sudo systemctl status docker | grep "Active:"
else
    echo "No containers to remove."
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Works 🔍
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Checks for Containers:&lt;/strong&gt; The script starts by checking if there are any existing Docker containers. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Removes Containers:&lt;/strong&gt; If containers are found, it removes all of them. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restarts Docker:&lt;/strong&gt; After cleaning up, the script restarts Docker to ensure everything is running smoothly. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Displays Status:&lt;/strong&gt; Finally, it shows the status of Docker to confirm that everything is active and working. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Use It 💡
&lt;/h2&gt;

&lt;p&gt;Using this script is super easy. Just follow these simple steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save the script as &lt;code&gt;docker-cleanup.sh&lt;/code&gt; (recommend to  save it on &lt;code&gt;home&lt;/code&gt; dir)&lt;/li&gt;
&lt;li&gt;Open your terminal. &lt;/li&gt;
&lt;li&gt;Execute the script
&lt;code&gt;bash docker-cleanup.sh&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A Personal Touch 🤗
&lt;/h2&gt;

&lt;p&gt;I face Docker environment issues regularly. This script has become my go-to solution, and I find myself using it at least once a day before I start working. It's simple, effective, and saves me a ton of time and hassle. I hope it works just as well for you! 🤞&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/itayeylath/docker-cleanup-script/blob/main/README.md" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8s7w5u56mz1ezifjwrv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8s7w5u56mz1ezifjwrv.png" alt="Image description" width="728" height="735"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>docker</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>Google Analytics With React Typescript</title>
      <dc:creator>Itay Eylath</dc:creator>
      <pubDate>Thu, 04 Jul 2024 11:55:02 +0000</pubDate>
      <link>https://forem.com/itayeylath/google-analytics-with-react-typescript-j9f</link>
      <guid>https://forem.com/itayeylath/google-analytics-with-react-typescript-j9f</guid>
      <description>&lt;h3&gt;
  
  
  What is GA ⁉️ 😯
&lt;/h3&gt;

&lt;p&gt;Google Analytics (GA) is a powerful tool for tracking and analyzing website traffic and user behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's how it operates:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GA collects data from your website using a JavaScript tracking code that you embed in your site’s pages. This code gathers information about your visitors and sends it to Google's servers, where it is processed and made available in various reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  How's the implementation Work?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useGoogleAnalytics.ts&lt;/code&gt;  as custom hook is the &lt;strong&gt;primary&lt;/strong&gt; file for integrating with GA.&lt;br&gt;
We're using an object to handle GA integration for flexibility and future-proofing.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GoogleAnalyticsProvider.tsx&lt;/code&gt; as a provider component to wrap the &lt;code&gt;Routes&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;App.tsx&lt;/code&gt; modify your file by add &lt;code&gt;GoogleAnalyticsProvider&lt;/code&gt; component &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Approach?&lt;/strong&gt; ♻️ &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Support multiple: functionalities, easily manage page views, event tracking, and post-initialization configurations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Future proofing: If we switch from ReactGA to another solution (e.g., a future GA version), we only need to update this object, not every instance in our codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React Way: This method aligns with React’s best practices by using a component to handle side effects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Comments In the code
&lt;/h2&gt;

&lt;p&gt;Search it on the App &lt;code&gt;// Recommend:&lt;/code&gt; and &lt;code&gt;// Remark:&lt;/code&gt; to understand logic and getting the implantation better in your App!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/itayeylath/google-analytics-react-ts" rel="noopener noreferrer"&gt;GitHub Repo: 'google-analytics-react-ts'&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useGoogleAnalytics.ts.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
import ReactGA from 'react-ga4';

// Recommend: implement it with env variables to keep it as a secret 
export const trackingId = "GA_ID"
const appVersion = "APP_VERSION"
// Remark: use user ID in your app to make the analyze better
// Recommend: implement it with Redux 
const id = "user-id"

const useGoogleAnalytics = () =&amp;gt; {

  useEffect(() =&amp;gt; {
    if (trackingId) {
      try {
        ReactGA.initialize([
          {
            trackingId,
            gaOptions: {
              anonymizeIp: true,
              clientId: id
            }
          }
        ]);
        ReactGA.set({ app_version: appVersion });
      } catch (error) {
        // Recommend: reporting this error to an error tracking service
        console.log("Error initializing Google Analytics", { Error: error });
      }
    }
  }, [id]);

  const setOption = (key: string, value: unknown) =&amp;gt; {
    ReactGA.set({ [key]: value });
  };

  const setUserId = (userId: string | number) =&amp;gt; {
    setOption("userId", userId);
  };

  const sendData = (type: string, data: Object) =&amp;gt; {
    ReactGA.send({ hitType: type, ...data });
  };

  const trackPageView = (pagePath?: string) =&amp;gt; {
    if (!pagePath) {
      pagePath = location.href;
    }

    setOption('app_version', appVersion);
    sendData("pageview", { page: pagePath });
  };

  const trackEvent = (category: string, action: string, label?: string, value?: number) =&amp;gt; {
    setOption('app_version', appVersion);
    ReactGA.event({ category, action, label, value });
  };

  return {
    setOption,
    setUserId,
    trackPageView,
    trackEvent,
  };
};

export default useGoogleAnalytics;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;GoogleAnalyticsProvider.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, PropsWithChildren } from 'react';
import { useLocation } from 'react-router-dom';
import useGoogleAnalytics, { trackingId } from '../hooks/useGoogleAnalytics';

const GoogleAnalyticsProvider: React.FC&amp;lt;PropsWithChildren&amp;lt;{}&amp;gt;&amp;gt; = ({ children }) =&amp;gt; {
    const { trackPageView } = useGoogleAnalytics();
    const location = useLocation();

    useEffect(() =&amp;gt; {
        if (trackingId) {
            try {
                trackPageView(location.pathname + location.search);
            } catch (error) {
                // Recommend: reporting this error to an error tracking service
                console.log("Error executing trackPageView Google Analytics", { Error: error });
            }
        }
    }, [location, trackPageView]);
    // Remark: this allows GoogleAnalyticsProvider to wrap other components without affecting the UI
    return &amp;lt;&amp;gt;{children}&amp;lt;/&amp;gt;;
}

export default GoogleAnalyticsProvider;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;App.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { BrowserRouter as Router, Route, Routes, useLocation } from 'react-router-dom';
import './App.css';
import GoogleAnalyticsProvider from './providers/GoogleAnalyticsProvider';

const App: React.FC = () =&amp;gt; {

  return (
    // Remark: check in your App, the optimal placement for GoogleAnalyticsProvider-
    // to ensures early initialization to track all route changes but the errors still be captured (if you use an error tracking service)
    &amp;lt;GoogleAnalyticsProvider&amp;gt;
      &amp;lt;Routes&amp;gt;
        &amp;lt;Route
          path="/"
          element={
            &amp;lt;div&amp;gt;
              Google Analytics React TypeScript
            &amp;lt;/div&amp;gt;
          }
        /&amp;gt;
      &amp;lt;/Routes&amp;gt;
    &amp;lt;/GoogleAnalyticsProvider &amp;gt;
  );
}

export default App;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2 Ways Of Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1 . General Tracking (the current repo) 😎
&lt;/h3&gt;

&lt;p&gt;💪 &lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple Initialization: Your setup ensures that Google Analytics is initialized only once when the GAInitializer component mounts.&lt;/li&gt;
&lt;li&gt;Page View Tracking: By providing a method to track page views, you can manually ensure that each page visit is logged.&lt;/li&gt;
&lt;li&gt;Custom Events: The trackEventBuilder method offers flexibility to track various user interactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎 &lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manual Page View Tracking: Since you're only wrapping the App component and not each route change, you must manually call trackPageView on each route change, which is prone to human error if forgotten.&lt;/li&gt;
&lt;li&gt;Lack of Route Change Tracking: Without automatic tracking of route changes, you might miss logging some page views if trackPageView is not called explicitly in each component.&lt;/li&gt;
&lt;li&gt;Limited User Context: Your implementation does not track detailed user interactions or demographic data beyond what GA collects by default.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Add Event Tracking Function To EVERY Event We Want To Track 😴
&lt;/h3&gt;

&lt;p&gt;💪 &lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Granular Control: you have precise control over exactly which events are tracked and how they are labeled, allowing for very detailed and specific analytics data.&lt;/li&gt;
&lt;li&gt;Customization: each event can be customized with specific category, action, label, and value, providing rich insights into user behavior and interactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎 &lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintenance Overhead: as your application grows, managing numerous individual tracking calls can become time-consuming and difficult to maintain consistently.&lt;/li&gt;
&lt;li&gt;Code Duplication: you might end up repeating similar tracking code across multiple components or functions, leading to less DRY (Don't Repeat Yourself) code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Content Security Policy (CSP) 🚔
&lt;/h2&gt;

&lt;p&gt;To implement GA, include the GA script in your web application and set up tracking in your code. Configure your CSP to allow connections to GA servers by adding '&lt;a href="https://www.google-analytics.com" rel="noopener noreferrer"&gt;https://www.google-analytics.com&lt;/a&gt;' to your script-src and connect-src directives. If using Google Tag Manager, also include '&lt;a href="https://www.googletagmanager.com" rel="noopener noreferrer"&gt;https://www.googletagmanager.com&lt;/a&gt;' in your script-src directive, and always test your CSP configuration thoroughly.&lt;/p&gt;

&lt;h2&gt;
  
  
  References ©️
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://undercontr.medium.com/implementing-google-analytics-to-react-with-typescript-d36909726b38" rel="noopener noreferrer"&gt;Medium: 'Implementing Google Analytics to React with TypeScript'&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=iX0nulueBvU" rel="noopener noreferrer"&gt;YouTube: 'Add Google Analytics in React JS'&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>google</category>
      <category>analytics</category>
    </item>
  </channel>
</rss>
