AdSense and the GDPR in WordPress: How to Build a Setup That Holds Up
Putting ads and AdSense into WordPress without losing yourself in theme code, loading time and consent questions. A practical guide with a step by step setup.
You want ads or Google AdSense on your WordPress site, and you want a setup that is fast, maintainable and defensible. The usual route is to paste an AdSense snippet somewhere into the theme and hope it holds. That bill arrives later: at the next update, in the loading time, and on the consent question. This post shows how to steer ads from one place instead of sprinkling code across your files, what to watch on the privacy side, and what a clean setup looks like step by step.
One thing before the details: this is a practical orientation, not legal advice. The GDPR applies across the European Union in the same wording, but the rule that actually governs ad cookies comes from the ePrivacy Directive, and every member state wrote its own national version of it. Where the fine print of your own market matters, a lawyer in that market is the right address.
Why you should steer ads instead of scattering code
The moment you glue the first ad block into a theme file or a post, a small mess begins. At the next theme update the code may simply be gone. If you want one ad in ten places, you maintain it ten times. And if you want to know whether a position earns anything at all, you have no basis for the answer, because nothing is being measured.
Three reasons speak for managing ads in one place:
- Maintainability: one ad unit, one source. You change the code once and the ad updates everywhere you placed it.
- Performance: ad scripts are often the heaviest elements on a page. Loading them deliberately, lazy loading being the keyword, protects your loading time and with it your rankings.
- Law: advertising, personalised advertising in particular, touches data protection. Central control makes it far easier to release ads only after consent, instead of remembering it in every single snippet.
This is exactly where an ad manager such as Adjet comes in. You create ads as their own blocks, decide centrally about placement and rules, and see the effect in a local statistic. No more hunting through theme files. How that compares with the best known tool for inserting code is set out in our post on Ad Inserter.
What the GDPR and the ePrivacy rules actually ask of an ad
Personalised ads, the kind AdSense serves by default, usually set cookies or read similar identifiers to recognise a visitor again. Under European law that needs an active decision by the visitor, the consent everybody talks about. Two layers stack up here, and mixing them is the most common misunderstanding.
The GDPR governs the processing of personal data and lists the possible legal bases. The consent for storing or reading anything on the visitor device comes from the ePrivacy Directive, which is not directly applicable and had to be transposed by every member state on its own. In Germany that is the TDDDG, the successor to the TTDSG. In Spain it is article 22.2 of the LSSI. In France it is article 82 of the Loi Informatique et Libertés, enforced by the CNIL. In Italy it is article 122 of the Codice privacy, in the Netherlands article 11.7a of the Telecommunicatiewet. In the United Kingdom the pair is the UK GDPR and PECR. Different laws, different regulators, the same starting point: non essential technology only after the visitor agrees.
In practice that means:
- You normally need a consent banner, or a consent management platform (CMP), through which visitors can agree or refuse.
- Advertising that relies on consent based technologies should load only after that agreement, not before it.
- Ads are advertising and should be recognisable as such. European consumer law asks that commercial intent be identifiable, and a plain advertising label is the simplest way to satisfy it. Germany treats a clear label as good practice, the UK works through the CAP Code and the ASA, other markets have their own bodies.
The sore spot in most setups is timing. If the ad script is loaded at page load, it is often already active before anybody agreed to anything. That is why consent gating, which ties ads to the actual consent signal, is worth the ten minutes it takes to switch on.
Consent Mode v2 and Google rules of its own
Since March 2024 Google expects Consent Mode v2 from sites that show Google ads or measure with Google tags and have visitors from the EEA. Technically it passes four signals to the Google tags: ad_storage, analytics_storage, ad_user_data and ad_personalization. Without them you risk incomplete measurement, weaker remarketing and, in the worst case, restrictions on your Google Ads or AdSense account.
Google adds a rule of its own on top of the law. Publishers who serve ads to visitors in the EEA and the UK are expected to use a consent management platform from Google certified list, and the message itself is set up under Privacy & messaging in the AdSense account. Check that list before you settle on a banner, because swapping a consent tool after launch is a lot more work than picking the right one at the start.
Setting up AdSense in WordPress, step by step
Here is how a clean setup goes. The steps follow Adjet, but the principle carries over to any well built ad setup.
1. Create the ad unit
You have two ways in. Either you paste your own ad code, from a direct advertiser for example, or you use the AdSense wizard. For banners you sell yourself, a rotation plugin is the usual route, and we went through that option in our post on AdRotate. There you enter your publisher ID and the slot ID and get a responsive ad that adapts to the space it sits in. If you want, you can additionally load Google Auto ads, where Google itself picks the positions. AdSense also expects an ads.txt file in your domain root; that file has nothing to do with consent, but it belongs to a complete setup, and we walk through it in the post on setting up ads.txt in WordPress.
2. Choose placement and targeting
Now you decide where the ad appears. For automatic placement the usual positions are ready: before or after the content, after a given paragraph, or after the first image. If you want tighter control, you place manually with a shortcode, a Gutenberg block or a widget:
[adjet_ad id="1"]
For rotating ads you bundle several units into a group that is served by weighting:
[adjet_ad_group name="header"]
Targeting narrows things further: desktop, tablet or mobile only, certain post types, categories, tags or terms, each with exclusions as well. That way you can show a mobile ad only inside one category and keep it off your sales pages.
3. Turn on consent gating
This is the step most people skip. Switch on consent cookie gating, which works with the common consent tools. The ad then loads only once the consent tool signals agreement for advertising. Without agreement the slot simply stays empty instead of firing ad scripts unasked.
4. Switch on lazy loading and the ad label
Enable lazy loading so ads load only when they move into the visible area. Technically an IntersectionObserver watches whether the block is about to become visible. That saves loading time, especially for an ad far down the page. Switch on the optional advertising label as well, so ads stay recognisable as ads.
5. Check the effect in the statistics
After going live you look at the local statistic, a 30 day chart rendered as a plain SVG that shows impressions and clicks. The data stays in your database, there are no external calls to Adjet or hafenstudios. So you see which position and which format works for your readers, and you can switch off weak placements instead of guessing. For time limited campaigns there is campaign scheduling with an optional start and end time. One number to expect: AdSense reports Ad requests in its own dashboard, and an ad request that goes unfilled never becomes an impression. The two dashboards will therefore never match exactly, and that is normal.
Keeping performance in view
Ads and loading time are a balancing act. A few simple rules help:
- Less is more: three considered placements often work better than eight that clutter the page and drive readers away.
- Use lazy loading: anything below the first visible area does not have to load immediately.
- Test positions: use the statistic to remove ads with weak effect instead of constantly adding new ones.
If you are tidying up your WordPress site anyway, clean URLs and redirects are worth a look at the same time. How to solve that properly is in the post on setting up 301 redirects in WordPress, because there too the point is to handle a technical matter centrally instead of scattered.
Steer your ads instead of scattering code
Adjet brings automatic placement, an AdSense wizard, consent gating, lazy loading and local statistics into one cockpit, with no external calls. Its own cookie banner with Google Consent Mode v2 is built in.
Conclusion
Putting ads and AdSense into WordPress is not a question of quickly copied code, it is a question of clean control. Manage ads centrally, serve them only after consent, load them late and label them as advertising, and you are on solid ground technically, legally and on loading time. And because you measure what works, you end up earning more with fewer ads. Adjet is open source under GPLv2, brings its own capability (manage_adjet) and a REST API (adjet/v1), and hands none of your data to the outside. What every plugin costs, Adjet included, is on our pricing page. And to repeat the sentence that matters: this is an orientation, not legal advice, so check the fine print of your own market with someone qualified there.
Common questions about AdSense and ads in WordPress
Do I need a consent banner for AdSense in WordPress?
In the EU, usually yes. Personalised ads like AdSense normally set cookies or read similar identifiers, and that requires an active agreement. For this you need a consent banner or a consent management platform through which visitors can agree or refuse. The rule comes from the national ePrivacy law of your market, for example the TDDDG in Germany or PECR in the UK, and not from the GDPR alone. This is an orientation, not legal advice; check the details for your own market with someone qualified.
When may an ad be loaded?
Advertising that relies on consent based technologies should load only after the agreement, not already at page load. In Adjet you switch on consent cookie gating for exactly this: it works with the common consent tools and loads an ad only once the consent tool signals agreement for advertising. Without agreement the slot simply stays empty instead of firing ad scripts unasked. Lazy loading via IntersectionObserver adds a second layer, so even consented ads load when the reader scrolls them into view.
Do I have to label ads as advertising?
Labelling is the safe route. Ads are advertising, and European consumer law asks that commercial intent be identifiable to the reader. How that is enforced differs by country: Germany treats a clear label as good practice, the UK works through the CAP Code and the ASA. Adjet ships an optional advertising label you can simply switch on, without touching any code, so readers can always tell which content is paid and which is not.
What does lazy loading do for ads?
Lazy loading makes sure an ad is only loaded once it actually moves into the visible part of the screen. Technically an IntersectionObserver watches whether the ad block is about to become visible. That saves loading time, especially for an ad further down the page, and it protects your Core Web Vitals. In Adjet lazy loading can be switched on together with consent gating, so both mechanisms work into each other.
Is Adjet free and how do I set up AdSense with it?
Adjet is open source under GPLv2. You create an ad through the AdSense wizard, enter your publisher ID and slot ID and get a responsive ad that adapts to the space; optionally you also enable the Google Auto ads loader. Placement happens automatically, before or after the content for example, or manually via a shortcode like [adjet_ad id="1"], a Gutenberg block or a widget. For automation there is a REST API at adjet/v1 and a dedicated capability called manage_adjet.