Multiple Regression Analysis, Explained Simply

Does content length help ranking? Do backlinks bring traffic? Do faster pages convert better?
Taken one at a time, these questions almost always get the same lazy answer: “yes, a bit”. The trouble is that in the real world factors never arrive one at a time. Long pages also tend to attract more links; pages with more links are often the most carefully made, and maybe the slowest too. Everything moves together, and the question that really matters is a different one: *which of these factors weighs on traffic net of the others?*

We saw, talking about correlation, that we can measure how much two variables move together; and with simple linear regression that we can use one to predict the other.
But one correlation at a time is blind to the tangle: it risks handing the same medal to a factor and to its companion, without being able to tell them apart. It is the doorway to a trap we already know, Simpson’s paradox: an association that flips sign or vanishes as soon as we account for a third variable. Multiple regression is the tool that tackles precisely this head-on — many causes together, each measured while holding the others fixed.

What we will cover:


Why one correlation at a time is not enough

Suppose we measure, on our own site, the correlation between content length and the traffic pages receive. We will almost certainly find it positive: longer pages get more traffic.
The temptation, at that point, is every hurried consultant’s shortcut: “I’ll write longer and traffic will rise”. But that correlation, on its own, does not tell us why long pages do better. Do they do better because they are long, or because — being long and well made — they have collected more backlinks over the years, and it is the links that bring the traffic?

These are two completely different stories, with two opposite action plans, and the correlation between traffic and length blends them into a single number. To separate them we need to be able to ask: holding backlinks fixed, does length still matter?
That is exactly the question multiple regression can answer. Multiple regression does not measure whether a factor is associated with the outcome, but how much it contributes once all the others are held fixed: it is the difference between looking at the world one variable at a time and looking at it as a whole.


The equation: many causes, one effect

The shape of the equation is the natural expansion of the simple-regression one: instead of a single predictor we put in several, each with its own coefficient. We want to explain a response variable (unique) from a set of predictor variables:

\( y = b + a_1 x_1 + a_2 x_2 + \dots + a_k x_k \\ \)

where \( y \) is the variable we want to explain (traffic), \( x_1, x_2, \dots, x_k \) are the predictors (length, backlinks, speed), \( a_1, a_2, \dots, a_k \) are the regression coefficients and \( b \) is the intercept.
The heart of it all is the meaning of each \( a_i \): it is how much \( y \) changes when \( x_i \) increases by one unit and all the other variables stay constant. That “stay constant” is the magic — and the responsibility — of the method: it is there that the separation of effects happens, the very effects that stay tangled to the naked eye.

In other terms: multiple regression simultaneously estimates the contribution of each factor, cleansed of that of all the others in the model. The best way to grasp it is to watch it dismantle a case built on purpose to fool us.


An example: what drives a page’s traffic

Let me build in R an example table with sixty pages of a site. For each one I have the monthly traffic, the number of words, the backlinks received and the load time in seconds. In reality these data come from Search Console, a crawler and a link tool; here, being an example, I simulate them — but with a precise mechanism in mind, which will be our testing ground:

set.seed(42)
n <- 60
words   <- round(rnorm(n, 1200, 380)); words[words < 350] <- 350
speed   <- round(pmax(0.6, rnorm(n, 2.6, 0.8)), 2)
# longer content attracts more backlinks: here is the tangle
backlinks <- round(pmax(0, 0.018 * words + rnorm(n, 0, 6)))
# traffic is driven BY backlinks and speed, NOT by words
traffic <- round(38 * backlinks - 260 * speed + 900 + rnorm(n, 0, 220))
traffic[traffic < 0] <- 0

pages <- data.frame(traffic, words, backlinks, speed)

I built the data so that traffic really depends only on backlinks and speed, while length has no direct effect at all. But I also tied length to backlinks — long pages attract more of them — just as happens in reality. How tied are they?

cor(pages$words, pages$backlinks)
# [1] 0.81

A strong bond: 0.81. Let us now see what happens if, naively, we study traffic looking only at length, with a simple regression:

coef(summary(lm(traffic ~ words, data = pages)))
#              Estimate Std. Error t value  Pr(>|t|)
# (Intercept) 241.1577   137.9404   1.748 0.0857...
# words         0.6128     0.1088   5.635 0.0000...

The verdict looks overwhelming: every hundred extra words are worth some sixty extra sessions, with a tiny p-value (below 0.001). Length “matters”, and matters a lot.
If we stopped here, we would go and write an editorial directive — make all content longer — on a basis that is about to turn out a mirage. Let us add the other two factors to the model and see what remains of length:

model <- lm(traffic ~ words + backlinks + speed, data = pages)
coef(summary(model))
#              Estimate Std. Error t value Pr(>|t|)
# (Intercept) 1100.797   120.119    9.164  0.0000
# words          0.107     0.102    1.041  0.3025
# backlinks     29.444     4.804    6.129  0.0000
# speed       -322.943    34.515   -9.357  0.0000

Here is the reversal. The length coefficient has collapsed from 0.613 to 0.107, and its p-value has jumped to 0.30: no longer distinguishable from zero.
Length, holding backlinks and speed fixed, brings almost nothing. What in the simple regression looked like its merit was in fact a reflection of the backlinks: long pages get more traffic not because they are long, but because — being long — they attract more links, and it is the links that do the work.

Traffic against number of words, with points coloured by backlink level. The red line is the simple regression: slope +0.61, length "seems" to drive traffic. The dashed green line is the effect of length holding backlinks and speed fixed: almost flat. The points with many backlinks (dark blue) cluster in the top right — they are the ones creating the apparent slope.
Traffic against number of words, with points coloured by backlink level. The red line is the simple regression: slope +0.61, length "seems" to drive traffic. The dashed green line is the effect of length holding backlinks and speed fixed: almost flat. The points with many backlinks (dark blue) cluster in the top right — they are the ones creating the apparent slope.

This is the deep meaning of multiple regression: it tells the factor that acts from the one that merely tags along. A task no correlation taken singly could ever perform.


Reading the coefficients: who really matters

From the full model we get three coefficients, but comparing them as they are would be a mistake: they have different units. The words coefficient (0.107) is per word, the backlinks one (29.4) is per link, the speed one (−323) is per second. Saying that speed “matters more” because its number is bigger makes no sense: a second and a word are not the same thing.

To compare them we must put them on the same scale. The standard way is to standardize all the variables — express them in standard deviations — and rerun the regression: the resulting coefficients, called standardized coefficients (or betas), tell how many standard deviations traffic changes for one extra standard deviation of each factor. Now they are comparable. I compute them in R by standardizing the data with scale:

z <- as.data.frame(scale(pages))
round(coef(lm(traffic ~ words + backlinks + speed, data = z))[-1], 3)
#    words backlinks    speed
#    0.104     0.610   -0.552

The picture becomes readable at a glance: backlinks are the engine (+0.61), speed a powerful drag (−0.55: the slower a page, the less traffic it gathers), and words a trifle (+0.10) that, as we already know, is not even distinguishable from chance.
A coefficient on its own, though, is not enough to trust: around every estimate there is a margin of uncertainty. If a coefficient’s confidence interval includes zero, that factor might well have no effect at all — which is precisely the situation of length.

Coefficient plot: each factor with its standardized coefficient and 95% confidence interval. Backlinks (+0.61) and speed (−0.55) sit clearly on one side of the zero line; words (+0.10) crosses it — an effect indistinguishable from chance. The length of the interval also tells the precision of the estimate.
Coefficient plot: each factor with its standardized coefficient and 95% confidence interval. Backlinks (+0.61) and speed (−0.55) sit clearly on one side of the zero line; words (+0.10) crosses it — an effect indistinguishable from chance. The length of the interval also tells the precision of the estimate.

A word of warning: in our example words and backlinks were correlated at 81%, and this is no harmless detail. When two predictors are too much alike, the model struggles to separate their effects, and the coefficients become unstable and imprecise — this is multicollinearity, one of the pitfalls we will tackle when talking about model diagnostics. Here it played in our favour, helping unmask the fake effect of length; but in general a non-significant coefficient does not prove a factor is irrelevant: it may only tell us that, given these tightly tangled predictors, we cannot isolate its contribution.


How valid is the model?

Knowing which factors matter is half the job; the other half is asking how well, overall, the model reconstructs reality. The reference measure is the coefficient of determination \( R^2 \): the share of traffic variability the model manages to explain, from 0 (nothing) to 1 (everything). I read it from the summary:

summary(model)$r.squared      # 0.805
summary(model)$adj.r.squared  # 0.795

An \( R^2 \) of 0.805 says our three factors together explain 80.5% of the traffic variability across pages — the rest is noise, or factors we did not include.
Beside it appears the adjusted \( R^2 \) (0.795), a slightly lower value: it penalizes the addition of useless variables, and should be looked at instead of the raw \( R^2 \) when comparing models with a different number of predictors. It guards against a trap: adding variables always raises the raw \( R^2 \), even when those variables add nothing real.

The most honest way to judge a model, though, is to watch it at work: put the traffic it predicts against the observed one, page by page. The closer the points hug the diagonal, the better the model captures reality.

Observed traffic against traffic predicted by the three-variable model. The points cluster around the diagonal (perfect prediction); the vertical grey segments are the gaps between observed and predicted. The model explains 80.5% of the variability.
Observed traffic against traffic predicted by the three-variable model. The points cluster around the diagonal (perfect prediction); the vertical grey segments are the gaps between observed and predicted. The model explains 80.5% of the variability.

A high \( R^2 \), it must be said, is not an automatic promotion: behind it lies a list of requirements the model takes for granted — that the relationships be linear, that the residuals behave well, that the predictors not be redundant (the multicollinearity of a moment ago). When these assumptions break, the coefficients stay numbers, but they stop being reliable. That is the territory of diagnostics, and it deserves a discussion of its own.


Try it yourself

The best way to fix the mechanism is to get your hands on it. Taking the code above, there are three interesting directions to explore:

  1. Drop backlinks from the model — lm(traffic ~ words + speed) — and watch what happens to the words coefficient: it grows large and “significant” again. It is the counter-proof that the fake effect lives only as long as the confounder stays out of the model.
  2. Add a completely made-up, random variable (pages\( noise <- rnorm(60)) and put it back into the model: watch the raw \)R^2\( rise by a hair and the adjusted \)R^2$ hold still or fall. That is the practical meaning of the adjustment.
  3. Change the generating mechanism: make traffic depend also on words (add a + 0.3 words to the traffic formula) and check that now, in the full model, the length coefficient survives. It serves to feel* the difference between a real effect and a merely apparent one.

A hint: the structure never changes — you fit the model, read the coefficients holding the others fixed, check the \( R^2 \) and the observed-predicted cloud. It is by playing with the variables in and out of the model that you grasp how much of what we call a “ranking factor” is cause and how much, simply, company.


So far our response variable has been a number that flows without jumps — traffic, which can be 300 sessions or 1,520. But very many SEO questions do not have this shape: a page converts or does not convert, a user returns or does not return, a keyword breaks into the first page or stays out. The answer is a yes or a no, and then a line predicting continuous numbers is no longer enough: we would need a model that predicts a probability, forced to stay between 0 and 1. That is the job of logistic regression, the next step of our path.


Further reading

If you want to go deeper into multiple regression, the interpretation of coefficients holding the others fixed and the reading of \( R^2 \) — the very backbone of what we built here — An Introduction to Statistical Learning by James, Witten, Hastie and Tibshirani is the book I recommend: it builds the linear-model framework with care, always starting from applied problems, and its hands-on R labs let you reproduce every step — including the traps of correlated predictors.

Leave a Reply

Your email address will not be published. Required fields are marked *