Last updated: 2024-06-18
Track how many people open a shared Google Spreadsheet by embedding a pixel that fires a Google Analytics 4 event each time the spreadsheet loads. This method uses a server-side image request to log visits without requiring users to click external links or accept app permissions.
A client created an ROI calculator using Google Spreadsheets as a brand utility. Before investing in converting it to a custom website form, they wanted to measure actual usage. Standard tracking methods fail: bit.ly links are bypassed when the spreadsheet is shared directly or via Google's native share feature; Google Apps Script counters display warnings on clone and require manual inspection of the spreadsheet itself (which increments the counter).
Instead of Apps Script, use the old-school image pixel technique: embed an =IMAGE() formula that fetches an image from a server script. The server script fires a Google Analytics 4 event and returns a 1×1 pixel, triggering GA4 tracking each time the spreadsheet is opened.
=IMAGE() to request the image from your script.Place this script on a PHP-enabled website (or use a no-code alternative like Integromat for Webflow or static HTML generators). A developer should vet the code before deployment.
Measurement ID and API secret:
$measurement_id = "G-XXXXXX";
$api_secret = "XXXXXXXXXX";
Replace with your GA4 credentials (see steps below).
Event name:
$event_name = $_GET['e'] ?: "ImagePixelEvent";
Defaults to ImagePixelEvent; customize via query string parameter e.
Image URL:
$image_link = urldecode($_GET['i']) ?: "https://www.example.com/logo.jpg";
Defaults to a logo; customize via URL-encoded query string parameter i.
Client identification:
$ip = str_replace('.', '', $_SERVER['REMOTE_ADDR']);
Note: Due to Google's image proxy, the source IP will typically appear as Google's proxy, not the user's actual IP.
$data = array(
'client_id' => $ip,
'user_id' => '123',
'events' => array(
'name' => $event_name
)
);
$datastring = json_encode($data);
$post_url = 'https://www.google-analytics.com/mp/collect?api_secret=' . $api_secret . '&measurement_id=' . $measurement_id;
$ch = curl_init($post_url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $datastring);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $post_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
curl_setopt($ch, CURLOPT_POST, TRUE);
$result = curl_exec($ch);
header('Content-type: image/jpeg');
imagejpeg(imagecreatefromjpeg($image_link));
<?php
$api_secret = "12345-XXXXXXXXXX";
$measurement_id = "G-XXXXXXXXX";
$event_name = $_GET['e'] ?: "ImagePixelEvent";
$image_link = urldecode($_GET['i']) ?: "https://www.example.com/logo.jpg";
$ip = str_replace('.', '', $_SERVER['REMOTE_ADDR']);
$data = array(
'client_id' => $ip,
'user_id' => '123',
'events' => array(
'name' => $event_name
)
);
$datastring = json_encode($data);
$post_url = 'https://www.google-analytics.com/mp/collect?api_secret=' . $api_secret . '&measurement_id=' . $measurement_id;
$ch = curl_init($post_url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $datastring);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $post_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
curl_setopt($ch, CURLOPT_POST, TRUE);
$result = curl_exec($ch);
header('Content-type: image/jpeg');
imagejpeg(imagecreatefromjpeg($image_link));
?>
Use with caution and have your developer review it before deploying to production.
Once your developer deploys the script (e.g., at www.tld.com/amazingpixel.php), use this formula in a cell:
=IMAGE("https://www.tld.com/amazingpixel.php?v="&NOW())
The v parameter with NOW() appended ensures the URL changes on each recalculation, triggering a fresh request.
To customize the event name or image URL from within the spreadsheet:
=IMAGE("https://www.tld.com/amazingpixel.php?v="&NOW()&"&i=ENCODED_IMAGE_URL&e=CustomEventName")
Replace ENCODED_IMAGE_URL with your encoded URL and CustomEventName with your chosen event name.
The image pixel method works anywhere an external image URL can be embedded:
Pro Tip: Use a dedicated GA4 account for shared or external tracking where you cannot control who accesses it.
Before third-party JavaScript became standard, image pixels were the primary method for tracking users across websites.