Knowledge

How to Detect Geo-Personalized and Dynamic Pricing Across Markets

Prices vary by place, time and person, and a single observation cannot tell which. How to design paired, controlled checks that separate the three.

Matt Brown

Matt Brown

September 16, 2026 · 8 min read

“Competitor X charges different prices in different places” is one of the most common findings in pricing analysis, and one of the least reliable. Two observations that disagree prove that the price varied. They do not prove why.

A price can differ because of where the shopper is, when they looked, or who they appear to be. Those are three different mechanisms with three different commercial and legal implications, and a collection setup that does not separate them will attribute all three to whichever one the analyst expected to find.

This guide is about detecting price variation in a way that survives scrutiny: designing the comparison so that a difference points to a cause.

Three mechanisms that look identical in a spreadsheet

Geographic pricing. The price depends on the shopper’s market, region or city. Different currencies, taxes and competitive conditions make this common and usually unremarkable.

Dynamic pricing. The price depends on time: demand, inventory, competitor moves, time of day. Two shoppers in the same place at different moments see different prices.

Personalized pricing. The price depends on attributes of the individual shopper: device, browsing history, account status, loyalty tier, or a model’s estimate of willingness to pay.

A single observation from market A on Monday and a single observation from market B on Tuesday cannot distinguish any of these. The observations differ in place and time, and possibly in session state as well. Everything in this guide follows from fixing that.

Principle one: change one thing at a time

Detection is an experiment. For each comparison, hold every condition constant except the one you are testing.

To test forVaryHold constant
Geographic pricingMarket or cityTime, device, session state
Dynamic pricingTimeMarket, device, session state
Device-based pricingDevice profileMarket, time, session state
Session or history effectsSession state (fresh versus established)Market, time, device

The most important constant is time, because almost everything online is repriced continuously. If you want to test geography, the observations from different markets need to be taken simultaneously, within seconds of each other, not an hour apart. Otherwise dynamic pricing contaminates every geographic finding.

Principle two: measure your own noise first

Before claiming that two markets differ, establish how much the same market differs from itself.

Run a control pair: two observations from the same city, at the same moment, with identical device profiles and fresh sessions. If the control pair disagrees, you are seeing A/B tests, rotating promotions, cache effects or randomised pricing, and any cross-market difference smaller than that noise means nothing.

Repeat the control pair across the day and across products. The distribution of within-market differences is your noise floor, and every other comparison is judged against it.

Principle three: repeat before you conclude

One simultaneous comparison is still one observation. Real geographic or personalized pricing is persistent: the same condition produces the same direction of difference, observation after observation.

A workable standard is to repeat each comparison across several days and times, and to treat a difference as real only when it is larger than the noise floor, consistent in direction, and present across repeats. A difference that appears once and never again is noise or an experiment on the retailer’s side, not a pricing policy.

Remove the confounders that masquerade as personalization

Most apparent price discrimination dissolves once these are controlled.

Currency. Compare in the shopper’s displayed currency, then convert with a dated rate. Never compare a converted number from one market against a displayed number from another.

Tax display. Some markets show prices including tax and some without. A 20% gap that matches a VAT rate is not a pricing decision.

Shipping and fees. A lower item price with a delivery charge is not a lower price. Capture the full basket cost where you can.

Stock and variant differences. The same product name may be a different variant, pack size or model in another market. Match on identifiers, not titles.

Store or fulfilment assignment. Retailers with local inventory price by store. A city-level difference may be two different stores, which is geographic pricing by another route.

Cached pages. A cached page can show a price that is no longer live. Record response headers and prefer uncached observations for the comparison itself.

Designing the collection

The collection layer has to deliver exactly the conditions each comparison requires, and it has to prove it delivered them.

Real vantage points per market. A request from a datacenter range in one country does not see what a shopper in another country sees. Residential proxies with country and city targeting provide local observation points. With the Shifter gateway, the market goes in the credentials against p.shifter.io:443:

customer-USERNAME-country-fr-city-paris-sid-trial-0412-a:PASSWORD
customer-USERNAME-country-fr-city-paris-sid-trial-0412-b:PASSWORD
customer-USERNAME-country-de-city-berlin-sid-trial-0412-c:PASSWORD

The first two lines are the control pair: same city, separate sessions, fired at the same moment. The third is the cross-market comparison.

Verify every exit. Record the actual exit location of each observation rather than trusting the request. A comparison whose exit landed in the wrong city is not a comparison, and it is the most common way geographic findings go wrong.

Fresh sessions by default. Use a new session identifier per trial so each observation starts clean. When testing history effects, hold one session deliberately across a sequence of page views instead. The distinction is covered in sticky vs rotating residential proxies.

Consistent locale signals. Language, timezone and headers should match the market the exit claims, or the retailer sees an inconsistent visitor and may serve a default. See matching proxy geo, timezone and locale.

Simultaneous firing. Trigger all observations in a comparison together, and record timestamps to the second so the analysis can confirm they were close enough.

What to record for every observation

FieldWhy it matters
Product identifierGuarantees the comparison is the same item
Displayed price, currency and tax basisAvoids the three most common false findings
Delivery cost and feesFull-basket comparison
Requested and verified exit locationProves the vantage point
Device profileIsolates device effects
Session stateFresh or established, and for how long
Timestamp to the secondProves simultaneity
Response headersDetects cached pages
Raw page or screenshotEvidence for any claim made later

The case for treating observation context as part of the dataset is set out in the vantage-point standard, and the risk of drawing conclusions from an unbalanced set of vantage points in your residential proxy pool is a sample, not the internet.

What you can and cannot conclude

External observation can show that a price differs consistently under a specific, controlled condition: a market, a device type, a session state. That is a strong and useful finding.

It cannot show the algorithm behind it, and it cannot prove that a price was set for a specific individual. Detecting individual-level personalization would require observing the site as many distinct real customers, and creating accounts or personas to do so can breach a retailer’s terms. Keep claims to what the controlled comparisons actually support: “prices on mobile are consistently higher in this market”, not “this retailer personalises prices”.

Where it matters commercially or legally, remember that rules differ by jurisdiction. In the EU, for example, traders must tell consumers when a price has been personalised on the basis of automated decision-making. Your findings can inform that kind of assessment, but they are evidence, not a legal conclusion.

From detection to monitoring

Once a pricing pattern is established, it is worth tracking rather than rediscovering. A continuous feed collected from the same markets, with the same controls, turns a one-off study into an early warning when a competitor changes policy. The operational side is covered in building a real-time competitive price feed, and travel pricing, where these effects are strongest, in scraping flight and hotel prices.

FAQ

How many markets should a detection study include?

As many as your commercial question needs, collected identically. Five markets with control pairs and repeats beat twenty markets observed once each.

How close together must simultaneous observations be?

Close enough that the retailer’s own repricing is unlikely to fall between them. For fast-moving categories that means seconds, not minutes. Record timestamps and discard comparisons that drifted.

Can I detect personalization based on browsing history?

Partly, by comparing fresh sessions against sessions that have browsed a defined path first. Keep it to what a controlled session can show, and stay within the site’s terms.

Why do my control pairs disagree?

Usually A/B tests, randomised promotions or caching. That disagreement is your noise floor, and it is the most important number in the study.

The bottom line

A price difference is a symptom, not a finding. To attribute it to geography, time or the individual shopper, change one condition at a time, fire comparisons simultaneously, measure your own noise with same-city control pairs, repeat before concluding, and strip out currency, tax, delivery and variant effects.

Verify every vantage point, record the full observation context, and keep claims to what the controls support. The product view is on the price intelligence monitoring page, with rates on the pricing page.

Ready to get started?

Try Shifter's residential proxies, 205M+ IPs, 195+ countries, from $0.10/GB.

Get Started