As cookies continue to degrade and tracking accuracy drops, Pinterestβs Conversion API (CAPI) is now crucial for eCommerce advertisers. By combining server-side tracking with product catalog events, you can significantly improve Pinterestβs ability to match users, attribute sales, and optimize campaigns for ROAS.
π§° Prerequisites
Requirement | Notes |
---|---|
OpenCart (v3.x or v4.x) | With template access |
Pinterest Tag ID | From Pinterest Ads Manager |
Pinterest CAPI Access Token | From Ads Manager (CAPI setup) |
GTM Web + Server Containers | Installed and deployed |
Product Feed Catalog | Synced via Pinterest Business Manager |
π― What Youβll Track
Event | Purpose |
---|---|
PageVisit |
Product pageview |
AddToCart |
Intent event |
Checkout (Purchase) |
Conversion + value |
Product ID | Synced with Catalog Feed (via model in OpenCart) |
ποΈ Implementation Plan
OpenCart Pages β Web GTM Pushes Event β Server GTM Receives + Sends to Pinterest CAPI
πΉ Step 1: Generate Pinterest Access Token
- Go to Pinterest Ads Manager β Conversions β API Access
- Create a new CAPI token
- Save:
- Pinterest Tag ID (e.g.,
2612238051234
) - Access Token
- Pinterest Tag ID (e.g.,
πΉ Step 2: Setup DataLayer Push on Product Page
Edit: catalog/view/theme/*/template/product/product.twig
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
event: 'pinterest_view_item',
product_id: '{{ product.model }}',
product_name: '{{ product.name|escape('js') }}',
value: '{{ product.price }}',
currency: '{{ session.currency }}',
event_id: 'pin_{{ product.product_id }}_{{ microtime(true) | round(0, 'common') }}'
});
</script>
πΉ Step 3: Track AddToCart on AJAX Cart Add (Optional Enhancement)
Update the controller handling add to cart
(usually catalog/controller/checkout/cart.php
) to also respond with a DataLayer-friendly payload (or track via MutationObserver if it’s client-side JS).
For simplicity, letβs inject on product pages using a click listener in Web GTM.
πΉ Step 4: Track Purchase on Success Page
In catalog/controller/checkout/success.php
:
$order_id = $this->session->data['order_id'];
$order_info = $this->model_checkout_order->getOrder($order_id);
$products = $this->model_checkout_order->getOrderProducts($order_id);
$items = [];
foreach ($products as $p) {
$items[] = $p['model'];
}
$email = strtolower(trim($order_info['email']));
$phone = preg_replace('/\D/', '', $order_info['telephone']);
$data['pinterest_purchase'] = json_encode([
'event' => 'pinterest_purchase',
'product_ids' => $items,
'value' => $order_info['total'],
'currency' => $order_info['currency_code'],
'email' => hash('sha256', $email),
'phone' => hash('sha256', $phone),
'event_id' => uniqid('pin_purchase_', true)
]);
In success.twig
:
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({{ pinterest_purchase|raw }});
</script>
πΉ Step 5: Web GTM β Set Up Triggers
Trigger 1: pinterest_view_item
Trigger 2: pinterest_add_to_cart
Trigger 3: pinterest_purchase
β Each trigger sends an event to the Server GTM endpoint (e.g., via fetch or GA4 transport)
Optional JS Fetch Forwarding:
fetch('https://gtm.yoursite.com/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
event_name: '{{DL - event}}',
product_ids: {{DL - product_ids}},
value: '{{DL - value}}',
currency: '{{DL - currency}}',
email: '{{DL - email}}',
phone: '{{DL - phone}}',
event_id: '{{DL - event_id}}',
action_source: 'website'
})
});
πΉ Step 6: Setup Pinterest CAPI in Server-Side GTM
- Import or create a Pinterest Conversion API Tag (use custom HTTP request tag or template)
- Request URL:
https://api.pinterest.com/v5/events
- Payload Example:
{
"event_name": "checkout",
"event_time": {{Timestamp}},
"event_id": "{{event_id}}",
"action_source": "website",
"user_data": {
"em": "{{email}}",
"ph": "{{phone}}"
},
"custom_data": {
"currency": "{{currency}}",
"value": {{value}},
"content_ids": {{product_ids}},
"content_type": "product"
}
}
- Header Setup:
Header | Value |
---|---|
Authorization | Bearer YOUR_ACCESS_TOKEN |
Content-Type | application/json |
- Trigger: Custom Trigger for each event name:
Event equals pinterest_purchase
Event equals pinterest_view_item
Event equals pinterest_add_to_cart
πΉ Step 7: Ensure Deduplication
- Send unique
event_id
in both pixel and CAPI (if you also implement client pixel) - Pinterest automatically deduplicates based on
event_id
π§ͺ QA & Debugging
Tool | Use |
---|---|
Server GTM Preview | Verify event data and API response |
Pinterest Event Manager | Confirm CAPI events |
Chrome β DevTools β Network | Validate fetch or pixel delivery |
Pinterest Tag Helper Extension | Debug client-side tags |
π Bonus: Set Cookie for epik
(Pinterest Click ID)
In header.twig
:
<script>
const epik = new URLSearchParams(window.location.search).get('epik');
if (epik) {
document.cookie = `epik=${epik}; path=/; max-age=2592000; SameSite=Lax`;
}
</script>
β
You can later read this cookie in Server GTM via event.data.cookie.epik
.
π¦ Architecture Overview
[OpenCart Product or Success Page]
β
[dataLayer Push (Web GTM)]
β β
[Pixel (optional)] [Fetch β Server GTM]
β
[Pinterest CAPI]