Setting Up Goals and Conversions in Yandex.Metrica
Metrica supports two goal types: automatic (page visits with depth, calls, forms) and manual (JavaScript events). For advertising in Yandex.Direct, goals are used in automatic bid management strategies — proper setup directly affects lead cost.
Tracker and Initialization
<!-- Metrica Tracker — before </head> -->
<script type="text/javascript">
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();
for(var j=0;j<document.scripts.length;j++){if(document.scripts[j].src===r){return;}}
k=e.createElement(t);a=e.getElementsByTagName(t)[0];k.async=1;k.src=r;a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(COUNTER_ID, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true, // session recording
ecommerce: "dataLayer", // name of array for e-commerce data
});
</script>
<noscript>
<div><img src="https://mc.yandex.ru/watch/COUNTER_ID" style="position:absolute; left:-9999px;" alt=""/></div>
</noscript>
COUNTER_ID is the numeric tracker ID from Metrica settings.
Goal Types
JavaScript Event (Most Flexible)
// Simple goal
ym(COUNTER_ID, 'reachGoal', 'GOAL_IDENTIFIER');
// Goal with parameters
ym(COUNTER_ID, 'reachGoal', 'form_submitted', {
form_type: 'contact',
page: window.location.pathname,
has_phone: true,
});
// Goal with value (for ROI calculation in Direct)
ym(COUNTER_ID, 'reachGoal', 'purchase', {
order_id: 'ORDER-789',
revenue: 14500,
});
GOAL_IDENTIFIER must match the identifier set in tracker settings → "Goals".
Goal Setup in Metrica Interface
- Tracker → "Goals" → "Add Goal"
- Type: "JavaScript Event"
- Identifier:
form_submitted(same as in code) - Value (optional): fixed or from event parameters
URL-based Goal (for Thank You Pages)
Type: Page visits
URL contains: /thank-you
No JS needed — works automatically on page visit.
Conversions for Key Scenarios
// Lead form submission
document.getElementById('lead-form').addEventListener('submit', function() {
ym(COUNTER_ID, 'reachGoal', 'lead_form_submit', {
form_location: this.dataset.location ?? 'unknown',
});
});
// Phone click
document.querySelectorAll('a[href^="tel:"]').forEach(link => {
link.addEventListener('click', () => {
ym(COUNTER_ID, 'reachGoal', 'phone_click', {
phone: link.href.replace('tel:', ''),
page: window.location.pathname,
});
});
});
// Email click
document.querySelectorAll('a[href^="mailto:"]').forEach(link => {
link.addEventListener('click', () => {
ym(COUNTER_ID, 'reachGoal', 'email_click');
});
});
// Chat opening
document.getElementById('chat-button').addEventListener('click', () => {
ym(COUNTER_ID, 'reachGoal', 'chat_opened');
});
// Page scroll to form block
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
ym(COUNTER_ID, 'reachGoal', 'form_visible');
observer.disconnect();
}
});
}, { threshold: 0.5 });
observer.observe(document.querySelector('#contact-section'));
E-commerce
Metrica supports e-commerce via dataLayer. Must set array name in tracker init (ecommerce: "dataLayer").
// Product list view
dataLayer.push({
ecommerce: {
currencyCode: 'RUB',
impressions: [
{
id: 'SKU-001',
name: 'Professional Plan',
category: 'Subscription',
price: 2990,
position: 1,
},
],
},
});
// Add to cart
dataLayer.push({
ecommerce: {
add: {
products: [{
id: 'SKU-001',
name: 'Professional Plan',
category: 'Subscription',
price: 2990,
quantity: 1,
}],
},
},
});
// Purchase
dataLayer.push({
ecommerce: {
purchase: {
actionField: {
id: 'ORDER-789',
revenue: 14500,
tax: 500,
shipping: 300,
coupon: 'PROMO10',
},
products: [
{
id: 'SKU-001',
name: 'Professional Plan',
category: 'Subscription',
price: 13700,
quantity: 1,
},
],
},
},
});
Visit and User Parameters
Parameters allow segmenting audiences in reports:
// Visit parameters (linked to specific visit)
ym(COUNTER_ID, 'params', {
visit_params: {
source_form: 'popup',
ab_variant: 'B',
user_type: 'new',
},
});
// User parameters (saved between visits)
ym(COUNTER_ID, 'userParams', {
UserID: 'usr_12345',
plan: 'pro',
registration_date: '2024-01-15',
company_size: 'smb',
});
// UserID for cross-device tracking
ym(COUNTER_ID, 'setUserID', 'usr_12345');
Linking with Yandex.Direct
For Direct's automatic strategies:
- Direct → "Campaign Editing" → "Strategy" → "Pay per conversion"
- Select goal from Metrica (tracker must be added to campaign)
- Set conversion cost target
Important: goal must accumulate minimum 10 conversions in last 28 days for auto-strategy to work properly.
Offline Conversions via API
If conversion happens offline (call closed to deal, invoice paid), upload to Metrica:
# Upload offline conversions
curl -X POST \
'https://api-metrika.yandex.net/management/v1/counter/COUNTER_ID/offline_conversions/upload' \
-H 'Authorization: OAuth YOUR_TOKEN' \
-H 'Content-Type: text/csv' \
--data-binary $'UserId,Target,DateTime,Price,Currency\nClientId123,purchase,2024-01-15T14:30:00,25000,RUB'
Fields:
-
ClientId— from cookie_ym_uidor viaym(id, 'getClientID', callback) -
Target— goal identifier -
DateTime— ISO 8601 -
Price— conversion value
Debugging
// Check tracker initialization
window.ym // should be function
// Get ClientID
ym(COUNTER_ID, 'getClientID', function(clientID) {
console.log('Metrika ClientID:', clientID);
});
// Test goal — should appear in Metrica → Debug
ym(COUNTER_ID, 'reachGoal', 'test_goal');
Chrome extension "Yandex.Metrica Debugger" displays all hits in DevTools panel with details.
Report data has 2-hour delay in Metrica. In "Debug" section, data is real-time.
Timeline
Tracker setup, 4–6 goals in code and interface — 1 day. E-commerce and visit parameters — 4–6 hours. Offline conversions and Direct integration — 1 more day.







