Questa guida mostra come implementare GA4 in uno shop PHP custom con gtag.js, tracciare gli eventi e-commerce principali e, opzionalmente, inviare eventi anche server-side via Measurement Protocol. È inclusa una sezione su GDPR/consenso.
1) Prerequisiti
- Proprietà GA4 creata e Measurement ID (formato
G-XXXXXXX). - (Opzionale) API Secret della proprietà GA4 per il Measurement Protocol.
- Struttura del tuo shop:
header.php,footer.php, pagina prodotto, carrello, checkout ethankyou.php.
2) Inserire gtag.js nel layout PHP
Nel tuo header.php (prima di </head>) incolla:
<?php
// config.php
$GA_MEASUREMENT_ID = 'G-XXXXXXXXX'; // <-- Sostituisci
?>
<script async src="https://www.googletagmanager.com/gtag/js?id=<?= htmlspecialchars($GA_MEASUREMENT_ID) ?>"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
gtag('js', new Date());
// Consent Mode base: aggiornalo dopo il consenso reale
gtag('consent', 'default', { 'ad_storage': 'denied', 'analytics_storage': 'denied' });
gtag('config', '<?= addslashes($GA_MEASUREMENT_ID) ?>');
</script>
3) Eventi e-commerce lato client (gtag)
3.1 view_item (pagina prodotto)
Nel controller PHP della scheda prodotto hai i dati del prodotto. Passali al front-end per l’evento:
<?php
// Esempio dati prodotto
$product = [
'id' => 'SKU-123',
'name' => 'Camicia Donna Colletto Classico',
'brand' => 'OXO Moda',
'category' => 'Abbigliamento > Camicie',
'variant' => 'Verde',
'price' => 29.90,
'currency' => 'EUR'
];
?>
<script>
gtag('event', 'view_item', {
currency: '<?= $product['currency'] ?>',
value: <?= number_format($product['price'], 2, '.', '') ?>,
items: [{
item_id: '<?= addslashes($product['id']) ?>',
item_name: '<?= addslashes($product['name']) ?>',
item_brand: '<?= addslashes($product['brand']) ?>',
item_category: '<?= addslashes($product['category']) ?>',
item_variant: '<?= addslashes($product['variant']) ?>',
price: <?= number_format($product['price'], 2, '.', '') ?>
}]
});
</script>
3.2 add_to_cart (click sul bottone “Aggiungi”)
Al click, invia l’evento con i dati della riga:
<button id="btnAddToCart">Aggiungi al carrello</button>
<script>
document.getElementById('btnAddToCart').addEventListener('click', function(){
gtag('event', 'add_to_cart', {
currency: '<?= $product['currency'] ?>',
value: <?= number_format($product['price'],2,'.','') ?>,
items: [{
item_id: '<?= addslashes($product['id']) ?>',
item_name: '<?= addslashes($product['name']) ?>',
price: <?= number_format($product['price'],2,'.','') ?>,
quantity: 1
}]
});
});
</script>
3.3 begin_checkout (ingresso checkout)
Quando l’utente apre il checkout, calcola totale e elenco articoli lato PHP e stampali nello script:
<?php
// $cartItems = [[id,name,price,qty], ...] e $currency
$value = 0; foreach($cartItems as $it){ $value += $it['price']*$it['qty']; }
?>
<script>
gtag('event', 'begin_checkout', {
currency: '<?= $currency ?>',
value: <?= number_format($value,2,'.','') ?>,
items: [<?php
$first = true;
foreach($cartItems as $it){
if(!$first) echo ','; $first=false;
echo json_encode([
'item_id' => $it['id'],
'item_name' => $it['name'],
'price' => (float)$it['price'],
'quantity' => (int)$it['qty']
]);
}
?>]
});
</script>
3.4 purchase (pagina di ringraziamento)
Su thankyou.php, dopo aver creato l’ordine in PHP, invia l’evento “purchase” con ID univoco:
<?php
// Dati ordine confermato
$orderId = $order['id']; // es. ABC123
$currency = $order['currency']; // EUR
$value = $order['total']; // 99.90
$tax = $order['tax']; // 8.90
$shipping = $order['shipping']; // 5.00
$coupon = $order['coupon'] ?? null;
$items = $order['items']; // array con id, name, price, qty
?>
<script>
gtag('event', 'purchase', {
transaction_id: '<?= addslashes($orderId) ?>',
currency: '<?= $currency ?>',
value: <?= number_format($value,2,'.','') ?>,
tax: <?= number_format($tax,2,'.','') ?>,
shipping: <?= number_format($shipping,2,'.','') ?>,
coupon: '<?= $coupon ? addslashes($coupon) : '' ?>',
items: [<?php
$first = true;
foreach($items as $it){
if(!$first) echo ','; $first=false;
echo json_encode([
'item_id' => $it['id'],
'item_name' => $it['name'],
'price' => (float)$it['price'],
'quantity' => (int)$it['qty']
]);
}
?>]
});
</script>
transaction_id deve essere unico per evitare duplicati in GA4.4) (Opzionale) Invio server-side con Measurement Protocol (PHP)
Utile come fallback (ad blocker) o per convalida. Richiede Measurement ID e API Secret (Admin GA4 → Data Streams → Web → Measurement Protocol API secrets).
<?php
function ga4_send_purchase_server_side($measurementId, $apiSecret, $clientId, $purchasePayload){
$endpoint = "https://www.google-analytics.com/mp/collect?measurement_id={$measurementId}&api_secret={$apiSecret}";
$body = json_encode([
'client_id' => $clientId, // es. genera UUID v4 e salvalo in cookie _cid
'events' => [[
'name' => 'purchase',
'params' => $purchasePayload
]]
], JSON_UNESCAPED_SLASHES);
$ch = curl_init($endpoint);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10
]);
$resp = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [$http, $resp];
}
// ESEMPIO USO dopo ordine:
$clientId = $_COOKIE['_cid'] ?? bin2hex(random_bytes(16)); // genera se manca e salva cookie
setcookie('_cid', $clientId, time()+31536000, '/', '', true, true);
$payload = [
'transaction_id' => $order['id'],
'currency' => $order['currency'],
'value' => (float)$order['total'],
'tax' => (float)$order['tax'],
'shipping' => (float)$order['shipping'],
'items' => array_map(function($it){
return [
'item_id' => $it['id'],
'item_name' => $it['name'],
'price' => (float)$it['price'],
'quantity' => (int)$it['qty']
];
}, $order['items'])
];
list($status,$resp) = ga4_send_purchase_server_side('G-XXXXXXX','YOUR_API_SECRET',$clientId,$payload);
// Logga $status per debug
?>
5) Consenso e GDPR (base)
- Mostra un banner cookie che consenta/nega Analytics.
- Se accetta, aggiorna Consent Mode:
<script> // dopo consenso gtag('consent', 'update', { 'analytics_storage': 'granted', 'ad_storage': 'denied' }); </script> - Se nega, mantieni “denied” e non inviare eventi opzionali (o usa Consent Mode v2 con pings limitati).
6) Verifica e debug
- GA4 → Report → In tempo reale per vedere eventi live.
- DebugView (attiva
gtag('set', 'debug_mode', true)in staging). - Controlla la console browser per eventuali errori JS.
- Per server-side, logga lo status HTTP del Measurement Protocol (200 atteso).
Checklist rapida
- gtag.js caricato su tutte le pagine.
- Eventi:
view_item,add_to_cart,begin_checkout,purchase. - ID transazione univoco.
- Consent Mode e banner cookie attivi.
- (Opzionale) Fallback server-side con de-dupe.
