You launch ads in Yandex.Direct, but you don't know which specific actions on the site lead to leads. Without configured goals, Metrica is just a visit counter. We set up goals and conversions so that every micro-interaction (phone click, scroll to form, lead submission) is tracked and passed to ad campaigns. The result: you know exactly the cost per conversion and can manage bids automatically, reducing the cost per lead by 20–40%.
Goal setup is divided into two stages: implementing JavaScript events on the site and configuring rules in the Metrica interface. The first requires a developer, the second an ad manager. We handle both stages, providing a ready-made configuration with documentation. Our experience: over 50 successful projects in Metrica integration.
What problems we solve
Loss of micro-conversions. Without JavaScript goals, you won't see phone clicks, AJAX form submissions, scrolls to important blocks. We implement events that fire on any user interaction, even if the page doesn't reload.
Incorrect attribution of offline conversions. A call processed by a manager or invoice payment is not recorded in Metrica. Through the API, we upload offline conversions, linking them to the visit and ad channel.
Complexities with e-commerce tracking. Online stores lose data on views, add-to-cart, and purchases. We configure the dataLayer for accurate funnel tracking.
Our approach gives a +40% increase in attribution accuracy compared to standard configurations.
How to set up goals for all key actions?
Counter and initialization
<!-- Metrica counter — 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,
ecommerce: "dataLayer",
});
</script>
<noscript>
<div><img src="https://mc.yandex.ru/watch/COUNTER_ID" style="position:absolute; left:-9999px;" alt=""/></div>
</noscript>
COUNTER_ID — the numeric counter ID from Metrica settings.
JavaScript event (most flexible type)
// Simple goal
ym(COUNTER_ID, 'reachGoal', 'GOAL_IDENTIFIER');
// Goal with parameters (params)
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 the counter settings → 'Goals'.
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 number 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');
});
// 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 (combined block)
// 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 parameters, user parameters, and debugging
// Visit parameters
ym(COUNTER_ID, 'params', {
visit_params: { source_form: 'popup', ab_variant: 'B', user_type: 'new' },
});
// User parameters
ym(COUNTER_ID, 'userParams', {
UserID: 'usr_12345',
plan: 'pro',
company_size: 'smb',
});
// UserID for cross-device tracking
ym(COUNTER_ID, 'setUserID', 'usr_12345');
// Check counter initialization
window.ym // should be a function
// Get ClientID
ym(COUNTER_ID, 'getClientID', function(clientID) {
console.log('Metrika ClientID:', clientID);
});
// Test goal
ym(COUNTER_ID, 'reachGoal', 'test_goal');
Why are conversions not passed to Yandex.Direct?
The most common reason is that the goal hasn't accumulated 10 conversions in the last 28 days. Direct's auto-strategies require minimal statistics. Also check that the counter is linked to the campaign and the goal identifier matches. The Yandex.Metrica Debugger allows you to check goal firing in real time. More details on Yandex.Metrica goals.
Linking with Yandex.Direct
- Direct → 'Edit campaign' → 'Strategy' → 'Pay for conversions'
- Select a goal from Metrica (the counter must be added to the campaign)
- Set the target cost per conversion (recommend based on historical data)
Important: the goal must accumulate at least 10 conversions over the last 28 days for the auto-strategy to work correctly.
Offline conversions via API
If a conversion happens offline (call closed in deal, invoice payment), it can be uploaded to Metrica via API. Send a POST request to https://api-metrika.yandex.net/management/v1/counter/{COUNTER_ID}/offline_conversions/upload with a CSV file containing fields: UserId, Target, DateTime, Price, Currency. UserId is taken from the cookie _ym_uid or via ym(id, 'getClientID', callback).
What's included in turnkey goal setup
- Audit of the current counter and ad campaigns
- Implementation of JavaScript goals for all key actions (form, phone, email, chat, scroll)
- Configuration of e-commerce layer with product and order data transfer
- Connection of visit and user parameters for segmentation
- Integration with Yandex.Direct and auto-strategy setup
- Upload of offline conversions via API (if needed)
- Documentation of all events and employee training
- Guarantee of correct data transfer for 30 days
Comparison of goal types
| Goal type | Complexity | Application | Example |
|---|---|---|---|
| JavaScript event | High | Any action on site (click, scroll, form submission) | reachGoal('form_submit') |
| URL goal | Low | Thank-you pages, redirects to external sites | URL contains /thank-you |
| Composite goal | Medium | Multi-step funnels (cart → checkout → payment) | Visiting 3 pages in a row |
JavaScript goals are 1.5 times more accurate than URL goals for tracking micro-conversions.
Setup stages and duration
| Stage | Duration | Description |
|---|---|---|
| Analytics | 2–4 hours | Audit of current goals, gathering business metric requirements |
| Design | 1–2 hours | Development of event scheme, selection of goal types |
| Implementation | 4–8 hours | Integration of JavaScript code, configuration in Metrica interface |
| Testing | 2–4 hours | Debugging via 'Yandex.Metrica Debugger' extension and real-time check |
| Deployment | 1 hour | Launch to production, monitoring for 2 days |
How to debug a goal if it doesn't fire?
Use the 'Yandex.Metrica Debugger' extension. Open the 'Events' tab and perform the target action on the site. If the goal doesn't appear, check the goal identifier and counter initialization. Also ensure the code fires after DOM content loaded.Practical example
For an online store with 5000 products, we configured an e-commerce layer that passes data on views, add-to-cart, and purchases. After implementation, the cost per lead dropped by 35% thanks to switching to the 'Pay for conversions' auto-strategy. Additionally, we uploaded offline conversions from the CRM, increasing attribution accuracy by 40%.
Contact us to get a consultation on setting up goals for your project. Order goal and conversion setup today — we guarantee transparency and full documentation.







