Cross language attribution: measuring one set of campaigns across Ireland, Germany, Austria and Switzerland
TL;DR
Difficulty: Intermediate
- A market is a country you ship to. A language is a version of the content. Keep them, and the site version, as separate columns.
- Ad platforms over claim, GA4 under counts, the shop database has the true total. Use each for what it does well.
- Name campaigns market first, then language, and map every label to a market in one written table.
- Correct for consent per market, then reconcile platform claims against orders every month, before anyone cuts a market.
German speaking markets look like one audience and behave like three countries, and an Irish shop selling into them gets four sets of numbers that never agree. I show why the ad platforms, GA4 and the shop database count differently, then work through an invented Galway outdoor brand's October to show how a mapping table, a per market consent correction and a monthly reconciliation turn a market that looked dreadful into one of its better ones.
The point: a market is not a language, and a campaign is not a market
An Irish shop that sells into Germany, Austria and Switzerland runs one set of campaigns in two or three languages across four countries. The ad accounts then report by campaign, analytics reports by country and by browser language, and the shop's own database knows where each parcel went. Those are three different ways of slicing the same orders, and they rarely agree.
Most of the damage I see comes from reading one slice as if it were another. A German language campaign is treated as "Germany", although Austria and most of Switzerland read German too. A Swiss visitor whose browser is set to French is filed under French. A platform that only saw the visitors who pressed accept is compared with a market where far fewer press accept. And then a market gets cut that was actually doing fine.
The fix is not a cleverer model. It is four plain habits: one naming convention, country and language as separate dimensions, a written market mapping table, and a monthly reconciliation of platform claims against what the shop shipped, market by market.
The shop in the examples is invented, and so are all its numbers. What I say about Google's products comes from Google's documentation, footnoted.
Worked example: an outdoor brand from Galway
Maumturk Outdoor is an invented outdoor clothing brand in Galway, run by Clodagh. It sells waterproof shells, fleeces and walking socks from maumturkoutdoor.example in five site versions: Irish English, German for Germany, German for Austria, German for Switzerland and French for Switzerland. It runs Google Ads and Meta campaigns in each market. It reports in euro, which keeps Germany and Austria simple, since they pay in the same currency as her customers at home. Switzerland pays in Swiss francs (CHF), so its figures are converted before they reach her reports.
In October Clodagh's ad accounts claim 840 orders. Her shop database says 1,250 orders arrived through a paid click. Her German campaigns look healthy and her Austrian ones look dreadful. Only the database figure is right, and by the end you will see why.
Three systems, three ways of counting
The ad platforms count conversions they can tie to their own clicks. Google Ads files a conversion under the date of the click that led to it, not the date the order happened, unless you switch to the "by conv. time" columns.1 Each platform only sees its own clicks, so if a customer clicked a Google ad on Monday and a Meta ad on Wednesday, both platforms may claim the same order. Neither is lying. Each is answering the question it was asked.
Google Analytics 4 (GA4) counts events on your site, and it gives credit for them with an attribution model. Today it offers three: data driven, paid and organic last click, and Google paid channels last click. The first click, linear, time decay and position based models were retired in November 2023.2 GA4 also has three scopes for its traffic source dimensions. "First user" dimensions keep the source that first brought a user. "Session" dimensions take the source that started each visit. The unprefixed dimensions, plain "Source" or "Medium", carry the credit from the attribution model you selected, and only those follow your model. The user and session scoped ones always use paid and organic last click.3 Mix the scopes in one report and you are adding apples to pears.
The shop database counts orders. It does not need consent to know that an order happened, where it was delivered and what it was worth, because recording an order is part of delivering on the contract. The consent article covers why that record is the shop's first party truth.
So the platforms over claim (each sees its own clicks), GA4 under counts (it only sees consenting visitors), and the database is right about the total but knows little about the journey. A sound method uses each for what it is good at.
Worked example: one order, three answers
A walker in Graz clicks a Maumturk Meta ad from the Austrian campaign on Tuesday, comes back on Thursday through a Google ad from the German campaign, accepts the cookie banner and buys a €140 shell. Meta claims the order (a click within its window). Google Ads claims it too, filed under Thursday and under the German campaign. GA4, with data driven attribution, might split the credit, say 0.7 to Google and 0.3 to Meta, and files the visitor under Austria. The database records one order, delivered to Austria. Three systems, one parcel, two full claims of credit, and Google Ads has already filed it under Germany.
Country and language are two dimensions, not one
The first habit is to keep country and language apart, everywhere.
GA4 does this for you, if you let it. Its Country dimension is "the country from which user activity originated", and its Language and Language code dimensions describe "the language setting of a user's browser or device".4 For visitors in the EU, Switzerland and the UK, Google says GA4 derives coarse location such as the country from the IP address, then discards the address without storing it.5 So country comes from where the visitor is, and language comes from how their device is set up. Neither tells you which version of your site they read.
Switzerland shows why this matters. It has four national languages. According to the Federal Statistical Office, in 2024 about 61% of the permanent resident population named German as a main language, 23% French, 8% Italian and 0.4% Romansh, while 24% named a language that is not a national language. Each person may name up to three main languages, so the shares add up to more than 100%.6 A Swiss market report that only counts German speakers misses roughly a quarter of the country. A language report that files Geneva under "French" mixes Swiss customers with French ones you may not even ship to.
My rule: a market is a country you sell to, with its own prices, delivery and legal setup. A language is a version of the content. A market can have several languages, and a language serves several markets. So every report that matters carries both, as separate columns, and a third one I add myself: the site version the visitor actually read.
Worked example: Maumturk's three columns
Maumturk's five site versions live in subfolders: /en-ie/, /de-de/, /de-at/, /de-ch/ and /fr-ch/. Clodagh adds the site version as an event parameter on every page view, registered in GA4 as a custom dimension called site_version. Now a single October visit has three labels. A visitor in Lausanne with a French browser reading /fr-ch/ is country Switzerland, language French, site version fr-ch. A visitor in Salzburg with an English browser reading /de-de/ is country Austria, language English, site version de-de. If Clodagh reported by language she would put them in with her English speaking customers at home in Ireland. If she reported by site version she would put them in Germany. Country says Austria, and that is the market that will ship and invoice the order.
Hreflang decides which page they land on
The second piece is upstream of analytics. If a Swiss walker searching in German lands on the page meant for Germany, with its prices and delivery terms, the market mapping is already broken before any tag fires.
Google Search Central's guidance is to tell Google about localised versions with hreflang annotations. The value is a language code in ISO 639-1 format, optionally followed by a region in ISO 3166-1 Alpha 2 format, so de-CH or en-IE. A region on its own is not allowed. Each version must list itself and every other version, and if two pages do not point to each other the annotations are ignored. The reserved x-default value marks the fallback page for anyone whose settings match none of the versions.7
One detail is worth knowing. Google says it does not use hreflang, or the HTML lang attribute, to detect the language of a page. It works that out for itself.7 Hreflang is a signal about which URL to show to whom, not a label that makes a page German. The page has to actually be in German.
Worked example: the shell jacket in five versions
The product page for Maumturk's Diamond shell carries six annotations in its head, identical on all five versions:
<link rel="alternate" hreflang="en-IE" href="https://maumturkoutdoor.example/en-ie/diamond-shell" />
<link rel="alternate" hreflang="de-DE" href="https://maumturkoutdoor.example/de-de/diamond-shell" />
<link rel="alternate" hreflang="de-AT" href="https://maumturkoutdoor.example/de-at/diamond-shell" />
<link rel="alternate" hreflang="de-CH" href="https://maumturkoutdoor.example/de-ch/diamond-shell" />
<link rel="alternate" hreflang="fr-CH" href="https://maumturkoutdoor.example/fr-ch/diamond-shell" />
<link rel="alternate" hreflang="x-default" href="https://maumturkoutdoor.example/" />
Each page lists itself and the other four, so every pair points both ways. A searcher in Zurich with a German browser is now far more likely to land on /de-ch/ with Swiss prices in francs. The site version column and the country column agree more often, and the mapping table below has less to fix. Hreflang does not guarantee it, so the mapping table still has the final word.
One property, many streams, one naming convention
People ask whether each country should get its own GA4 property. My answer is usually no.
Google's structure is account, then property, then data stream, where a data stream is "a flow of data from a customer touchpoint (e.g., app, website) to Analytics". A property can hold up to 50 data streams.8 Google leaves the choice of structure to you, and the property that combines several properties for a view across brands or regions, the roll up property, is a feature of the paid 360 product.8 So for a shop on the standard product, separate country properties mean separate reports that nobody can add up without exporting them.
One property with country, language and site version as dimensions gives you every market and the total from the same data. I only split properties when there is a real reason, such as a separate legal entity in a market, a separate team that must not see the others, or a data residency demand. "It feels tidier" is not one of them. GA4 handles several currencies within one property: send a currency with every value and it converts to the property's reporting currency at the previous day's exchange rate.9 For a shop reporting in euro, that conversion only touches the Swiss orders in CHF, since Germany and Austria already pay in euro. That is good enough for a monthly view, and your accounts are the place for the exact figure.
The naming convention matters more than the property layout. The UTM article covers the vocabulary in full. For several markets I add one rule on top: the campaign name starts with the market and then the language, always in that order, always lowercase, joined with underscores.
Worked example: Maumturk's campaign names
Clodagh's October campaigns are named like this:
ie_en_winter_shells
de_de_winter_shells
at_de_winter_shells
ch_de_winter_shells
ch_fr_winter_shells
The first part is the market, the second the language of the ad, the rest the theme. The same names go into utm_campaign on every Meta link and into the campaign names in Google Ads, where auto tagging keeps doing its job alongside. A report filtered to campaigns starting with at_ shows everything she aimed at Austria. A report on GA4's Country dimension shows everyone who was in Austria. Those are two different questions, and the naming makes both of them easy to ask.
One conversion definition across ad accounts
A good few shops that sell abroad end up with one Google Ads account per market. That is grand, as long as every account counts a purchase the same way.
Cross account conversion tracking lets a manager account own a conversion action and share it with its client accounts, measured with a single Google tag. Only the manager account can change these actions, and an account uses either its own conversion actions or the shared ones, not both. Google notes that switching does not lose the history, but campaigns that targeted a specific conversion action may fall back to the manager's default goals, so check the bidding afterwards.10
In my experience the shops that skip this end up with four slightly different "purchase" actions: one counting every conversion, one counting one per click, one with a 30 day window, one with 90 days. The accounts then disagree for reasons that have nothing to do with the markets.
Worked example: Maumturk's manager account
Clodagh's four Google Ads accounts sit under one manager account. She creates a single purchase conversion action there, set to count one conversion per click with the same window, value and tag, and shares it with all four. The old per account actions are switched to secondary so they no longer drive bidding. From the next day, a purchase means the same thing in Galway and in Graz, and any difference between the accounts is a difference between the markets.
Location targeting leaks across borders
One more source of mismatch sits in the ad platforms themselves. Google Ads' default location option, "Presence or interest", shows ads to people who are in or regularly in your target location, and also to people who have shown interest in it. Google calls this the default and recommended option, and notes that location targeting is a best effort without a guarantee of full accuracy.11
So a German campaign reaches Austrians and Swiss with an interest in Germany, and the German campaign claims their orders. Nothing is broken. Campaign and market are simply different columns.
Worked example: where Germany's orders really went
In October, Maumturk's German campaigns claim 280 orders across Google Ads and Meta. Clodagh joins those claims to GA4's Country dimension through the click ids and the campaign names. Of the 280, 40 came from visitors in Austria and 25 from visitors in Switzerland. Germany's own claim is therefore 280 minus 40 minus 25, which is 215. Austria's rises from the 40 its own campaigns claimed to 80. Switzerland's rises from 50 to 75. The total stays 840, it has just moved to the right countries.
The market mapping table
One small table maps every label your systems produce to a market. One person owns it, and every report joins to it.
Worked example: Maumturk's mapping table
| Market | Site versions | hreflang | Campaign prefix | GA4 country | Delivery country | Google Ads account |
|---|---|---|---|---|---|---|
| Ireland | /en-ie/ | en-IE | ie_ | Ireland | IE | Maumturk IE |
| Germany | /de-de/ | de-DE | de_ | Germany | DE | Maumturk DE |
| Austria | /de-at/ | de-AT | at_ | Austria | AT | Maumturk AT |
| Switzerland | /de-ch/, /fr-ch/ | de-CH, fr-CH | ch_ | Switzerland | CH | Maumturk CH |
The rule Clodagh writes under the table decides conflicts. For orders, the delivery country wins, because that is the market that carries the price, the tax and the returns. For visits without an order, the GA4 country wins. Campaign prefix and site version are kept as their own columns, so she can still see that a German campaign sold to Austria. One line of rule saves a meeting a month.
Consent rates differ by market, so correct per market
Here the consent article does the heavy lifting, and I only take its central idea. What a platform or GA4 observes is roughly the true number multiplied by the opt in rate, the share of all visitors who pressed accept. The opt in rate is different in every market, so a single correction for the whole shop is wrong in every market. The correction has to be done per market:
Here is the consent corrected estimate of conversions in market , is the number of conversions GA4 observed in that market (each order counted once), and is the opt in rate in that market, measured on your own banner as accepting visitors over all visitors. Dividing by a rate turns a sample back into an estimate of the whole, which is covered in Foundations: ratios and rates, and the reason this only holds if refusers behave like accepters is a question of conditional probability, in Foundations: probability. When they do not, the consent article gives the refined version with the ratio between the two groups' conversion rates.
Worked example: Maumturk's consent corrected October
Clodagh measures her opt in rate per market from her consent log: Ireland 62%, Germany 44%, Austria 48%, Switzerland 66%. These are invented for the example. GA4, with each order counted once, observed these paid orders by country: Ireland 360, Germany 165, Austria 66, Switzerland 62, which is 653 in total.
Ireland: , so about 581.
Germany: .
Austria: , so about 138.
Switzerland: , so about 94.
The corrected total is . The database says 1,250, so the correction lands within 5% overall. The leftover gaps are Ireland 19, Germany 25, Austria 12 and Switzerland 6. They are small and they point in one direction, which is what you would expect if accepting visitors convert a little differently from refusing ones. That is the cue to use the refined formula, or simply to trust the database for the totals, which is what I do.
Reconciling platform claims against orders
The monthly reconciliation pays for all the other habits. For each market, set what the platforms claim next to what the shop shipped:
is the coverage ratio for market , is the sum of the conversions the ad platforms claim for that market after mapping, and is the number of orders the shop database recorded as arriving through a paid click in that market. It is a plain ratio of two counts, see Foundations: ratios and rates. A ratio well below 1 means the platforms are missing orders, usually because of consent. A ratio above 1 means they are double claiming. Most real shops sit below 1 in the German speaking markets, and the useful thing is to watch whether the ratio moves.
What counts as "through a paid click" in the database has to be defined once and kept. I store the landing parameters of the ordering session with the order, and an order counts as paid if that session landed with a Google Ads click id or a paid utm_medium. It is a simple last click rule, but it is the shop's own and it does not depend on consent.
Worked example: Maumturk's reconciliation
Clodagh's database records these paid orders by delivery country: Ireland 600, Germany 400, Austria 150, Switzerland 100, which is 1,250 in total.
First, the view straight from the ad accounts, by campaign: Ireland 470, Germany 280, Austria 40, Switzerland 50.
The horizontal axis has two bars per market: the orders the ad accounts claim for that market's campaigns, and the actual paid orders the shop delivered there, the latter highlighted. The vertical axis is orders. Read straight off the ad accounts, the coverage is Ireland , Germany , Austria and Switzerland . Austria looks like a market that returns a quarter of what it should. That is the view on which budgets get cut.
Now apply the mapping from the location section. Germany drops to 215, Austria rises to 80, Switzerland to 75, and Ireland stays at 470. The coverage becomes Ireland 0.78, Germany , Austria and Switzerland .
The picture has turned round. Germany and Austria now sit together at about half, which is what you would expect from two markets with opt in rates in the mid forties. Switzerland and Ireland, with higher opt in rates, sit at three quarters or more. Nothing about the campaigns changed. Only the counting did.
One more check: the platforms claim 840 orders in total, but GA4 observed only 653, each counted once. The ratio says the platforms claim about 29% more orders than GA4 saw, and the difference is orders that both Google and Meta claimed. That overlap is the reason you never add the platforms' numbers together and call it a total.
Sharing the credit between channels, per market
Reconciliation tells you how many orders a market really produced. It does not tell you how to split them between Google and Meta. For that I borrow the shares from GA4's attribution, which sees the paths, and apply them to the database total, which has the right count:
is the share of credit for channel in market . is the attributed conversions GA4 gives channel in that market under your chosen model, using the unprefixed, event scoped dimensions. The sum adds the attributed conversions of every channel in the market, so the shares add up to 1. is the estimated number of orders credited to channel , and is the database total for the market, as before. Shares that add to 1 behave like probabilities, see Foundations: probability, and the division is the same ratio as in Foundations: ratios and rates. The assumption underneath is that refusing visitors split between channels the way accepting ones do. It is an assumption, and I say so in the report.
Worked example: is Austria worth the money?
In Austria, GA4's data driven model splits the 66 observed paid orders as 40.6 to Google Ads and 25.4 to Meta.
Google's share: .
Meta's share: . The two add to 1.
Credited orders, out of the 150 the database recorded: Google , so about 92. Meta , so about 58.
Now the spend. Austria is in the eurozone, so there is no conversion to worry about here. Google Ads' geographic report puts €2,100 of October spend on clicks from people in Austria, €1,800 from the Austrian account and €300 from the German one. Meta's breakdown by country gives €1,000. Cost per order: Google , Meta .
Compare that with what the Austrian ad accounts alone suggested: €1,800 of Google spend for 25 claimed orders is €72 per order, and €900 of Meta spend for 15 claimed orders is €60. Read from the platforms, Austria costs three to four times what it really costs. Read from the reconciliation, it is one of Clodagh's better markets.
The data path from click to market report
Here is the whole path in one picture, top to bottom.
Read it from the top. The click carries the labels. Hreflang and the site structure decide which version the visitor reads. The consent decision splits the visitors into two streams: one that analytics and the platforms can see, and one they cannot. Both streams meet again at the order, which the shop records in either case. The nightly join uses the mapping table to put every claim, every observed conversion and every order into a market. The report at the bottom is the only one I let anyone make budget decisions from.
What to do this month
If your reports do not agree with your bank account, this is the order I would work in.
First, write the mapping table and its rule for conflicts. It takes an afternoon.
Second, rename campaigns so they start with market and language, and fix the same names in your UTMs.
Third, add the site version as a custom dimension in GA4, and use the unprefixed source dimensions whenever you look at attribution.
Fourth, move the purchase conversion into a manager account if you run more than one Google Ads account.
Fifth, check your hreflang: every version lists itself and all the others, and the pages really are in the language they claim.
Sixth, start the monthly reconciliation per market, with your own opt in rates, and watch the coverage ratios move.
The old version of this article talked about BigQuery pipelines and matched cohorts. They have their place in a big shop. In the shops I have worked on, these six habits caught the expensive mistakes long before any model would have.
Sources
Footnotes
-
Google, Understand your conversion tracking data, Google Ads Help, https://support.google.com/google-ads/answer/6270625?hl=en
-
Google, Get started with attribution, Analytics Help, https://support.google.com/analytics/answer/10596866
-
Google, Scopes of traffic source dimensions, Analytics Help, https://support.google.com/analytics/answer/11080067
-
Google, Analytics dimensions and metrics, Analytics Help, https://support.google.com/analytics/answer/9143382
-
Google, EU, Switzerland, or UK focused data and privacy, Analytics Help, https://support.google.com/analytics/answer/12017362
-
Federal Statistical Office (FSO), Languages, main languages 1970 to 2024, FSO, 2026, https://www.bfs.admin.ch/bfs/en/home/statistics/population/languages-religions/languages.html
-
Google Search Central, Tell Google about localized versions of your page, Google for Developers, https://developers.google.com/search/docs/specialty/international/localized-versions
-
Google, Google Analytics hierarchy, Analytics Help, https://support.google.com/analytics/answer/9303323
-
Google, Currency reference, Analytics Help, https://support.google.com/analytics/answer/9796179
-
Google, About cross account conversion tracking, Google Ads Help, https://support.google.com/google-ads/answer/3030657
-
Google, About advanced location options, Google Ads Help, https://support.google.com/google-ads/answer/1722038