Velora — Lead & Ad Analytics

Beschreibung

Velora answers one question for a shop owner: which advertising brings back more money than it costs.

It counts each order once, across Google, Meta and every other paid channel, so two platforms cannot both claim the same sale. It shows what each channel returns per euro spent. And it names the step of the funnel that loses the most people — not as a chart to interpret, but as a sentence.

This plugin is the part that runs on your site. It is deliberately thin: it records which pages a visit saw and what was ordered, and sends that to your Velora account. No analytics logic runs in PHP, so it does not slow your site down.

What it does

  • Records page views and the campaign parameters a visit arrived with (UTM tags, Google and Meta click ids).
  • Sends WooCommerce orders — the order value and currency, not the shopper.
  • Detects form submissions from Contact Form 7, WPForms, Gravity Forms, Elementor Pro Forms and Fluent Forms.
  • Lets you mark specific pages as goals, for shops where the conversion is a booking or a call rather than an order.
  • Waits for consent. Nothing is linked to a returning visitor until your cookie banner says yes.

What it does not do

It does not store names, addresses, phone numbers or payment details. IP addresses are truncated before they are stored. It sets no third-party cookie and follows nobody across other websites.

External services

This plugin requires a Velora account and sends data to Velora’s API at https://api.veloraapp.io. Without that account the plugin does nothing — there is no local-only mode.

What is sent, and when

  • On each page view, once the visitor’s consent allows it: a random visitor identifier, the page URL, the referrer, the campaign parameters in the URL, the browser’s user-agent string, screen and window size, and a timestamp.
  • When a WooCommerce order is placed: the order identifier, its value and currency, and the timestamp. Where you enable it in Velora’s settings, a SHA-256 hash of the buyer’s e-mail address, used only to recognise a repeat customer. The e-mail itself is never sent.
  • When a tracked form is submitted: which form it was, the page it was on, and the timestamp.
  • Once, when you connect the site: your site’s URL, exchanged for the credential the plugin then uses to authenticate.

Data is processed on servers in the European Union and kept for three years, then deleted. You can erase everything at any time from Velora’s settings.

Velora is operated by Vertexly s. r. o., Karpatské námestie 10A, 831 06 Bratislava – Rača, Slovak Republic.

  • Terms of service: https://veloraapp.io/terms
  • Privacy policy: https://veloraapp.io/privacy
  • Data processing agreement: https://veloraapp.io/dpa

Installation

  1. Install the plugin through the WordPress plugins screen, or upload the folder to /wp-content/plugins/velora-analytics.
  2. Activate it.
  3. Open the Velora menu item and click Connect to Velora. You will be sent to veloraapp.io to sign in, and returned here automatically.

That is the whole setup. The plugin finds your forms and your WooCommerce hooks by itself.

FAQ

Do I need a Velora account?

Yes. The plugin is the client half of a hosted service; on its own it has nothing to report to.

Does it slow my site down?

The tracking script is small and sent with navigator.sendBeacon, which does not block the page. No analytics calculation happens on your server.

Is it GDPR compliant?

It is built for it. Nothing is linked to a person before consent, IP addresses are truncated on arrival, no personal contact details are collected, and a data processing agreement is in place with every account. Your visitors‘ data stays in the EU and is deleted after three years.

What happens if a visitor declines cookies?

They are counted as one anonymous visit — enough to keep the funnel honest, never enough to recognise them again.

Does it work without WooCommerce?

Yes. Form submissions and goal pages work on any WordPress site. WooCommerce adds order values, which is what makes the revenue side possible.

Rezensionen

Zu diesem Plugin liegen noch keine Rezensionen vor.

Mitwirkende und Entwickler

„Velora — Lead & Ad Analytics“ ist Open-Source-Software. Folgende Menschen haben an diesem Plugin mitgewirkt:

Mitwirkende

Änderungsprotokoll

1.0.24

  • Each sale now records whether the shopper allowed advertising, separately from whether they allowed measurement. Velora may count a sale on measurement consent alone, but sending it back to an ad platform is a different purpose that needs advertising consent, and a shopper can allow one and refuse the other. Only sales with advertising consent will ever be sent to Google Ads or Meta.

1.0.23

  • An order moved along in the back office is no longer credited to the person moving it. When Velora had not seen an order being placed and a shop manager later marked it paid, the sale was filed under the manager’s own visit — their browsing, their channel. It is now counted as a sale Velora did not see, which is what it is.
  • The count of sales Velora could not see no longer flickers. It was read through WooCommerce’s order search, which on shops that trim plugins per request sometimes came back empty — and an empty answer was reported as „none“, wiping the real figure until the next report restored it. The count is now read straight from the order tables, and when they cannot be read nothing is reported instead of a zero.
  • The consent banner is named correctly. „GDPR Cookies“ is a renamed copy of an older banner plugin and was reported under the original’s name; it is now called by its own. How consent is read does not change.
  • The shop’s timezone is reported, so „Today“ on the dashboard begins at the shop’s midnight rather than the reader’s.
  • A returning customer who types their Gmail address differently — with dots, with a +tag, or as googlemail.com — is recognised as the same customer. The address sent to ad platforms for matching is unchanged; the recognition uses a second, separate fingerprint.

1.0.22

  • The page a visitor arrives on is measured even when they accept the cookie banner only after it has loaded. Velora used to decide once, as the page was drawn, whether it was allowed to count — and on a visitor’s first page the banner has never been answered, so the answer was always no. The visitor accepted a moment later and that page, the one an ad points at and the only one carrying the campaign it came from, was never recorded. On the shop this was found on, more than half of visitors lost their arrival page this way, including a paid Facebook click that went on to buy and was credited to nothing. Velora now notices when the banner is accepted and records the arrival page then, with the time the visitor actually arrived. Nothing is recorded or stored before the visitor agrees.
  • A visitor who accepts the banner only on their second page no longer loses the ad that brought them. The browser still reports the page they came from, campaign and click id included, and Velora now takes the campaign from there when the page itself has none.

1.0.21

  • Orders placed on shops that switch plugins off per page are measured again. Several speed plugins decide, request by request, which plugins are allowed to run, and the checkout is one of the requests they trim hardest. Where Velora was not on that list, the order was created in a request Velora never saw: it was met hours later, when someone in the back office marked it done, by which time the shopper was long gone and the sale was filed as unmeasured. On the shop this was found on, thirty-one hours of trading produced twenty orders and not one measurement. Velora now keeps itself loaded on those requests. Nothing to configure; if the site does not allow it, the Velora screen says so instead of failing quietly.
  • Product views are no longer counted when no one is looking at a product. The view was recorded wherever the product template was drawn, including quick-view pop-ups and the extras shown beside a cart — so one shopper sitting on the checkout page could add a dozen product views without opening a single product. Measured on a live shop, two product views in three were of this kind, which made the first step of the funnel — the step every later one is compared against — about three times too big. Only a real product page counts now. Past figures are not rewritten; from the update onward the funnel narrows to the truth.

1.0.20

  • Product views on translated pages are counted again. Translation plugins that add a language to the address — /cs/, /de/ and so on, as Weglot and similar services do — put that segment where WordPress does not look, so a product page viewed in another language was not recognised as a product at all. On a cached shop that meant no product view and, from the browser’s side, no add-to-cart either, for every visitor browsing in a translated language: they fell out of the funnel at its first step even when they went on to buy. The product is now found behind the language segment. Nothing needs configuring, and a page that is not a product still records nothing.
  • The count of orders Velora could not measure now counts sales, not attempts. An order was counted the moment it was placed, which on a card checkout is before the payment has gone through — so a declined card, a closed bank window or an abandoned payment page stayed in the figure for good, and the account could report far more unmeasured orders than the shop actually took. The count is now worked out from the orders themselves: an order is included once it is paid, and drops out again if it is cancelled, refunded or its payment fails. Figures already reported for the last seven days correct themselves after the update.

1.0.19

  • Form submissions and contact clicks now follow the same rule as orders: a conversion Velora did not watch is not recorded. Until now a submission from a visitor with no tracking cookie still produced a lead — one with no journey behind it, counted as a conversion but belonging to no traffic source. That flattered the numbers. Expect fewer leads than before on a site behind a consent banner, and every one of them traceable to the visit that produced it.

1.0.18

  • Fixes a count that was too high. Moving an old order — marking it shipped, running a bulk action, letting a carrier or reminder plugin update it — was recorded as though a new order had just been placed that day. On a busy shop that inflated the „orders we could not measure“ figure well past the number of orders actually taken. Only orders placed in the last two days are now considered new, which is far longer than a checkout ever takes and far shorter than the age of anything a back office re-files. Orders already recorded are unaffected, and the figure corrects itself from the next day onward.

1.0.17

  • Your own test orders no longer count as sales. An order placed while you are signed in as an administrator or shop manager is marked as a staff order and left out of the reports entirely — not counted as a conversion, and not counted against your measurement coverage either, because it is not a customer’s order at all. This applies to a checkout you complete yourself on the shop front end; orders your staff key into the WordPress admin — a phone order, say — are treated no differently than before.
  • The admin area is no longer tracked. Opening wp-admin used to record a visit, so anyone working in the back office slowly accumulated a browsing history of their own dashboard. Those visits stop being recorded; the front end is unchanged.

1.0.16

  • Fixes a fault that stopped page views, product views, cart steps and campaign touches from being recorded at all. Every version from 1.0.12 onward carried it: one line of the plugin referred to its own main class by the wrong name, which made the call that sends an event fail outright — not return an error, fail. Orders were unaffected, because they travel a different path, which is why a shop could look like it was recording sales and nothing else. If your funnel has been empty since updating, this is why, and it is fixed.
  • Fixes a second fault introduced by 1.0.15: the per-day count of unrecorded orders was sent in a form the Velora API refused, and it refused the whole batch of events travelling with it. It only happened when there was nothing to count — which is the state every shop is in on the day it installs.
  • A status change on an order Velora declined to record no longer retries for a day against a sale that will never exist.
  • Nothing needs to be reconnected or reconfigured. Events sent while the above was broken are lost; everything from here on is recorded normally.

1.0.15

  • Velora now reports only the orders it actually watched happen, and the import of past orders is gone for good. Until now, an order placed without Velora seeing the visit behind it was still recorded, with the campaign read from WooCommerce’s own order attribution — which made the revenue total complete and made the product something it was never meant to be. On the shop this was built against, every single recorded order was of that kind: the whole reported revenue was WooCommerce’s answer presented as Velora’s, while Velora’s own funnel had seen 1,302 visitors and not one purchase it could call its own. Those orders have been deleted from the account and nothing recreates them.
  • What this costs is worth stating plainly. Behind a consent banner, Velora reports the sales of shoppers who accepted, and no others — on that shop, roughly a fifth of its orders. That is a fraction of the revenue, and it is the only fraction an independent measurement can stand behind. Your shop’s own order total remains your shop’s: the two numbers are meant to be compared, not merged, and a gap between them is information rather than an error.
  • An order Velora declines to record is marked as such on the order itself, so its later status changes no longer queue updates for a lead that will never exist.
  • Those declined orders are counted — a number per day, nothing else. No identifier, no value, no campaign; nothing that could be mistaken for a sale or credited to a channel. It is there because removing these orders from the reports also removed the only way to tell two situations apart: a shop where most shoppers decline consent, which is normal and lawful, and a shop where measurement has broken, which is not. Those look identical from the inside, and the second one has twice cost a live shop a day of selling while every screen showed a confident zero. Your account now says which of the two it is seeing, and what share of your orders it can speak for.

1.0.14

  • Orders placed through a block-based checkout are recorded again. WooCommerce creates such an order as a draft first and only turns it into a sale a moment later, by changing its status. Recording drafts would be wrong — most of them are abandoned carts — so they are skipped, and nothing was listening for the moment one became real. Every order the earlier versions recorded on the shop this was found on came from the one-off import of past orders; in the eighteen hours after that import finished, while the shop was selling, not one order was recorded live, and the status updates for those sales were queued against leads that were never created. The moment an order becomes real is now the moment it is recorded.
  • An order awaiting payment is recorded but not counted as revenue until the payment arrives. In WooCommerce „pending“ means exactly one thing — the order was placed and the money has not come back — and on a block checkout that is the status an order sits in between the shopper pressing the button and the card clearing. Counting it as a sale would count every abandoned card form, every closed 3-D Secure window and every decline the gateway does not mark as failed, and nothing would ever correct it. Such an order is recorded immediately so it cannot be lost, and the confirmation promotes it to a sale, normally within seconds. Orders already paid for are unaffected: they still count from the moment Velora sees them, which is the behaviour 1.0.12 introduced and the reason it exists.
  • The orders lost to the above are imported once, in the background, the same way 1.0.10’s import worked: bounded to recent orders, in small batches, stopping by itself. An order already recorded is left alone.
  • The plugin now tells your Velora account which version it is. This sounds like bookkeeping and is not: when a shop’s measured numbers move, the first question is whether the shop changed or the measurement did, and until now nothing recorded the one fact that answers it. A morning was spent on exactly that — a shop’s measured traffic fell fourfold overnight and three explanations fitted the data equally well, each calling for a different response. The version, and the date it arrived, now appear on the connection screen in your account.

1.0.13

  • An order recorded without the visitor’s own cookie now says so when it reports. Velora exists to be an independent record of which click produced a sale, and that only means something when it saw the visit itself. Where it did not — a guest order, a shopper who keeps no cookies, a gateway that creates the order out of view — the campaign is WooCommerce’s own record of where the visit came from. Such an order still counts as revenue, and Velora no longer credits a channel with it: agreeing with an ad platform using that platform’s own answer is not independent confirmation. Your reports will show fewer attributed orders and the same revenue, which is the honest version of what was already true.

1.0.12

  • Two more consent banners are understood. GDPR Cookie Consent (the WebToffee family) now has an adapter of its own, and any banner built on the IAB’s Transparency and Consent Framework is read through that standard — which covers banners nobody has written an adapter for, including ones that do not exist yet. A banner the plugin cannot read means consent never resolves to yes, so the shop measures nothing at all unless „assume consent“ happens to be switched on; that state is now reported to your Velora account and shown on the privacy screen instead of looking like a quiet shop.
  • The click identifier an ad sends with a visit is now recorded, not just which kind it was. Knowing a visit came from a Google ad was never enough to tell Google which click it was, and that is the one thing needed to send the order back so the platform’s bidding can learn from real revenue.
  • An order counts as a sale from the moment it is placed, instead of waiting for payment to be confirmed. Waiting is the riskier of the two: an order that is never marked paid — because the gateway confirms out of band, or because staff move statuses by hand — stayed uncounted indefinitely and said nothing about it. A sale that does fall through announces itself, and a refunded, cancelled or failed order moves the lead to lost as it happens.

1.0.11

  • The import of past orders introduced in 1.0.10 recovered the first twenty and then stopped, reporting itself finished. Two separate causes, both now fixed: it identified the orders still to do with a filter wc_get_orders() ignores — the same query asking for orders with the marker and orders without it returned the identical list — so every run re-read the same twenty; and it counted those re-reads as progress until it hit its own ceiling. It now walks orders by position instead of by filter, and counts only orders it actually imported.
  • The import no longer depends on WP-Cron. A large shop often turns WP-Cron off and drives it from a server crontab, and when that crontab is not running nothing says so — measured on a live shop, the follow-up batch was still waiting four hours later. The work now rides on requests the shop is already serving, a few seconds at a time, and on a front-end page only where the response can be delivered in full before the import starts.
  • A shop that ran 1.0.10 picks up where it left off rather than being skipped for having been marked finished.
  • An order’s status now reaches the reports. Every figure Velora exists to show — revenue, ROAS, what each channel returned, customer lifetime value — counts only orders marked won, and orders were being recorded as not-yet-resolved and left that way: the status was only ever changed by a later transition, and an order already paid for when it was recorded has no later transition to wait for. On one shop that was nineteen orders worth 20,963.92 showing as no revenue at all. The status is now read from the order when it is recorded, and orders recorded by an earlier version are corrected.
  • Payment is recognised without waiting for an order to be marked completed. Many shops never mark orders completed — the order ships and stays in processing — and for those, revenue was never counted at all. A failed payment is no longer counted as a sale.

1.0.10

  • Orders are recorded whatever placed them. The plugin listened for the action WooCommerce’s own checkout fires, but a payment gateway does not have to use that checkout: Stripe’s Payment Element and every express button — Apple Pay, Google Pay, Link — build the order themselves, and that action never runs. On a live shop with 95,000 orders this meant not one order ever reached the reports, while the same shop’s product views and cart events arrived normally. The order is now caught at the point WooCommerce itself creates it, which every checkout, every gateway, the admin screen and the REST API all pass through.
  • An order placed without a browser still knows where it came from. WooCommerce records the campaign on the order, and that is now used when the visitor’s own cookie is unavailable — a phone order typed in by staff, a gateway that creates the order in a request of its own, a shopper who keeps no cookies. Previously such a sale was attributed to nothing.
  • Orders placed while the above was broken are imported once, in the background. Bounded to recent orders, in small batches, and it stops by itself when there is nothing left to recover; a shop connecting for the first time imports nothing.

1.0.9

  • CookieYes is detected again. The check looked for a function CookieYes does not define, in any version, so every shop using it was treated as having no consent tool at all — and unless „assume consent“ happened to be switched on, that shop measured nothing and had no indication why. The consent categories were wrong too: CookieYes calls them analytics and advertisement, and this asked for statistics, which CookieYes has never used.
  • Once a consent tool has been seen, it stays seen. Some shops load a different set of plugins for AJAX and REST requests than for ordinary page views, which made consent resolve differently from one request to the next on the same visit.
  • Add-to-cart is now reported by the browser as well as by the server. On a live store only 2 of the 17 visitors who reached the checkout had a cart event, because that shop’s stack never ran this plugin on its AJAX add-to-cart request. The browser is not subject to that, and the step is deduplicated per visitor per minute, so a shop where both reporters work still counts one add to cart.
  • The checkout address step is recorded once per visitor rather than depending on a WooCommerce session being present, which it is not on every request that reports it.
  • Traffic from search engines and social networks is labelled as such. A month of Google organic arrived as www.google.com / referral — no organic search line existed anywhere in the reports — and Facebook traffic was split across facebook.com, m.facebook.com and l.instagram.com as three unrelated sources. Referrer hosts also drop their www., so one partner site is one row.

1.0.8

  • Product views are recorded again on shops that use page caching. The product-page hook runs in PHP, and a cached page never reaches PHP — so on a live store only 36 product views were recorded out of 218 real ones, and every cart step after them had nothing to follow. The view is now reported by the same always-live request that already rescues campaign parameters from cached landing pages.
  • A product view is counted once per visitor per minute, so a shop whose pages are sometimes cached and sometimes not does not count the same view twice.
  • The beacon is no longer refused on shops whose address is www.yourshop.com. The host check compared www.yourshop.com with yourshop.com as different sites, so for a visitor who arrived without the www every beacon call was rejected — and with it the campaign parameters from cached landing pages. A mismatched Origin header also no longer stops the referrer from being checked.

1.0.7

  • The device breakdown now covers every event instead of page views alone. Campaign touches, product views and cart events were sent without the browser’s user agent, so the server had nothing to read them from and filed them all as „unknown“ — the chart described a few per cent of your traffic and presented it as all of it.
  • Product views and cart events for a visitor with no cookie are now genuinely skipped. The check existed but did nothing: the event was still sent, refused by the server as incomplete, and the refusal put it in the retry queue.
  • A payload the server refuses is no longer retried. The queue re-sent anything that failed, every fifteen minutes for a day, including requests that could never succeed — on a busy shop, up to two hundred pointless calls a pass.

1.0.6

  • A visit from your own site is no longer counted as a referral. www.yourshop.com and yourshop.com were compared as different hosts, so every internal click on the www address opened a brand-new visit credited to your own domain — on a live shop that was the single largest „source“ in the funnel, and none of it was real traffic.
  • Campaign touches are recorded only for visitors whose browser keeps a cookie, the same rule product views already follow. A request with no cookie was given a fresh identity and a touch of its own, once per request, which is what crawlers do and what people don’t.
  • Known limitation: a direct, first-ever page view no longer logs a „direct“ touch before the visitor’s browser answers. Direct touches are shown in the journey path and never receive attribution credit, so reporting is unaffected.

1.0.5

  • Product views, cart events and goal pages are now recorded only for visitors whose browser keeps a cookie. A shop’s product pages are crawled constantly by feed fetchers, price comparison sites and AI crawlers, none of which run JavaScript or return cookies — each of those requests was becoming a brand-new one-page visitor, which on a live shop meant a hundred phantom people an hour drowning the real ones.
  • „Ingest reachable“ in the health check now turns to OK when events are actually arriving. It only ever counted leads, which are rare, so a shop sending page views every minute sat at „Pending“ next to a line saying the last event was seconds ago.

1.0.4

  • Visitors are now identified by one shared id that both the page’s script and the server can read. The old identifier was set by PHP alone, and on a shop behind a page cache PHP does not run for most page views — so the cookie was never delivered and almost every event invented a new visitor. One real shop produced 152 visitors from 166 events, and no funnel step could be connected to the one before it.
  • Campaign parameters are recorded through the same route, so a visit to a cached landing page no longer loses the utm_source, utm_campaign or click id it arrived with — the pages ads point at were the ones losing them.
  • The settings screen is now available in Slovak, Czech and Ukrainian as well as English. It was English on every site, including shops whose whole admin is in another language — and one of its switches decides whether the shop is measured at all.
  • Every section of this settings page now says what it is for and whether it needs a decision from you, instead of presenting switches with no explanation.
  • Goal pages now come from your Velora dashboard, which is the one place they are set. They used to be ticked here and listed there with neither side knowing about the other, so whichever screen you had open was wrong about your shop. This page shows what the dashboard says, and the thank-you pages it finds on your site each get an „Add in Velora“ button that opens the dashboard with the address already filled in — you press Save there.
  • Conversion pages now count one visit per visitor per day as intended. The 24-hour rule was written against an identifier that changed on every request, so it never applied.
  • The WooCommerce order confirmation page is no longer offered as a conversion page. Ticking it saved a setting that could never fire, and orders are already counted by the checkout hook — with their real value, which a page visit does not carry.
  • Removed the „Cost sync“ row from the health check. It always read „Pending“, including on shops with Google Ads and Meta connected and spend already arriving: the plugin cannot see ad connections, which belong to the Velora account rather than to this site. The dashboard answers that question.

1.0.3

  • Documented the external service the plugin depends on, per directory guidelines: what is sent, when, where it is processed, and how long it is kept.
  • Text domain now matches the directory slug, so translations actually load.
  • Admin redirects go through wp_safe_redirect(), with the portal host allow-listed rather than trusted implicitly.
  • Every cookie value read from a consent plugin is unslashed and sanitised.
  • The public event endpoint now accepts requests only from pages on this site, only while the site is connected, and only within a per-address rate limit.
  • Separated the plugin and author URIs.
  • Tested against WordPress 7.1.

1.0.0

  • First public release: page and campaign tracking, WooCommerce order events, form detection for five form plugins, goal pages, consent gating, and one-click connection to a Velora account.