Analytics Architecture on Webnode
Webnode is a closed website builder with restricted code injection capabilities. The platform provides limited access points for analytics implementation, and availability depends entirely on the subscription plan:
- Header/Footer Code Injection -- Available on Standard plan and above via Settings > Website Settings > Header/Footer code
- Custom HTML Widget -- An embeddable widget that accepts HTML and basic JavaScript, available on paid plans
- Webnode API -- Limited REST API for content management, not for template or code injection
Webnode does not expose template files, does not support server-side scripting, and does not provide a code editor for layout modification. All analytics implementation is constrained to the injection points above.
Plan-Based Access Matrix
| Feature | Free | Limited | Mini | Standard | Profi |
|---|---|---|---|---|---|
| Header/Footer code injection | No | No | No | Yes | Yes |
| Custom HTML widget | No | No | Yes | Yes | Yes |
| Custom JavaScript execution | No | No | Limited | Yes | Yes |
| E-commerce tracking | No | No | No | No | Yes |
Installing Tracking Scripts
Header Code Injection (Standard+ Plans)
Navigate to Settings > Website Settings > Header/Footer code > Header code:
<!-- Google Tag Manager -->
<script>
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');
</script>
In the Footer code field:
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
Custom HTML Widget (Mini+ Plans)
For plans that support the HTML widget but not header/footer injection, add an HTML widget to each page from the page editor:
- Open the page editor
- Click + to add a new element
- Select HTML from the widget list
- Paste your tracking script
<script>
// Inline GA4 -- use this only if header injection is unavailable
(function() {
var s = document.createElement('script');
s.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX';
s.async = true;
document.head.appendChild(s);
s.onload = function() {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXX');
};
})();
</script>
The HTML widget must be placed on every page individually -- there is no way to make it global.
Built-in Google Analytics Integration
Webnode offers a native Google Analytics integration under Settings > Website Settings > Google Analytics. Enter your Measurement ID (G-XXXXXXX). This method only supports basic pageview tracking with no custom events, no GTM, and no data layer.
Data Layer Implementation
Initialize a data layer in the header code injection field:
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
platform: 'webnode',
page_path: window.location.pathname,
page_title: document.title
});
</script>
Page Type Detection
Webnode uses URL patterns that vary by site configuration. Common patterns:
<script>
window.dataLayer = window.dataLayer || [];
var path = window.location.pathname;
var pageType = 'page';
if (path === '/' || path === '') pageType = 'home';
else if (document.querySelector('.blog-post, .wn-blog-post')) pageType = 'blog_post';
else if (document.querySelector('.blog-list, .wn-blog-list')) pageType = 'blog_index';
else if (document.querySelector('.product-detail, .wn-product')) pageType = 'product';
else if (document.querySelector('.cart-page, .wn-cart')) pageType = 'cart';
window.dataLayer.push({
page_type: pageType,
has_ecommerce: !!document.querySelector('.wn-shop, .shop-section')
});
</script>
Form Submission Tracking
Webnode's built-in forms submit via AJAX. Track submissions by observing the form:
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('form').forEach(function(form) {
form.addEventListener('submit', function() {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'form_submit',
form_id: form.id || 'webnode_form'
});
});
});
// Alternative: watch for success message appearance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node.nodeType === 1 && node.classList &&
node.classList.contains('form-success')) {
window.dataLayer.push({ event: 'form_success' });
}
});
});
});
var formContainers = document.querySelectorAll('.wn-form, .contact-form');
formContainers.forEach(function(container) {
observer.observe(container, { childList: true, subtree: true });
});
});
</script>
Common Issues
JavaScript Stripped on Lower Plans
Webnode's free and Limited plans strip <script> tags from HTML widgets. The code will appear in the editor but will not render on the published site. There is no workaround -- upgrade to a plan that supports custom JavaScript.
Header Code Not Firing
After adding header/footer code, the site must be republished. Click Publish in the editor toolbar. Draft/preview modes may not execute injected scripts.
HTML Widget Scope Limitations
The HTML widget creates an isolated container. Scripts inside it execute in the global scope but the widget's container <div> may have restricted CSS that hides or clips content. Avoid placing visible tracking elements (like noscript iframes) in HTML widgets.
Multilingual URL Handling
Webnode supports multilingual sites with language-prefixed URLs (/en/, /de/). The same page appears under different paths per language. Normalize paths for analytics:
var langPattern = /^\/(en|de|fr|es|cs|sk|pt|it|pl|hu|nl|sv|da|no|fi|ro|bg|hr|sl|el|tr|ja|ko|zh)\//;
var normalizedPath = window.location.pathname.replace(langPattern, '/');
No Server-Side Access
Webnode provides zero access to server-side code, HTTP headers, or response configuration. All analytics implementation must be client-side JavaScript. Server-side tracking (like server-side GTM) is not possible natively -- you would need an external server-side endpoint that receives client-side beacon requests.
E-commerce Tracking Requires Profi Plan
Product pages, cart, and checkout tracking are only functional on the Profi plan, which is the only tier with full e-commerce features. On lower plans, shop-related DOM elements do not exist.
Platform-Specific Considerations
Webnode API limitations: The Webnode REST API (api.webnode.com) provides endpoints for managing pages and content but does not expose template structure, injected code, or analytics configuration. It cannot be used for analytics auditing.
Responsive editor vs. published output: Webnode's editor renders pages differently than the published site. Always verify tracking code on the published version, not in the editor preview.
Cookie banner: Webnode includes a built-in GDPR cookie banner configured under Settings > Privacy & Cookies. It does not integrate with Google Consent Mode. The banner sets a consent cookie (wn_cookie_consent) that you can check before firing scripts:
var consent = document.cookie.match(/wn_cookie_consent=([^;]+)/);
if (consent && consent[1] === 'accepted') {
// Fire analytics
}
CDN and caching: Webnode serves sites through its own CDN. Cache invalidation after publishing is automatic but may take up to 5 minutes. Do not assume tracking code changes are live immediately after publishing.
Domain and SSL: Custom domains are available on Mini plans and above. SSL is provided automatically on all plans including the free tier. All analytics scripts must use HTTPS endpoints.