Title: Hafenstudios Ads – Ad Manager, AdSense &amp; Banner Ads
Author: hafenstudios
Published: <strong>30 Julai 2026</strong>
Last modified: 13 Ogos 2026

---

Search plugins

![](https://ps.w.org/hafenstudios-ads/assets/banner-772x250.png?rev=3628546)

![](https://ps.w.org/hafenstudios-ads/assets/icon-256x256.png?rev=3628546)

# Hafenstudios Ads – Ad Manager, AdSense & Banner Ads

 Oleh [hafenstudios](https://profiles.wordpress.org/hafenstudios/)

[Download](https://downloads.wordpress.org/plugin/hafenstudios-ads.2.2.0.zip)

 * [Details](https://ms.wordpress.org/plugins/hafenstudios-ads/#description)
 * [Reviews](https://ms.wordpress.org/plugins/hafenstudios-ads/#reviews)
 *  [Pemasangan](https://ms.wordpress.org/plugins/hafenstudios-ads/#installation)
 * [Pembangunan](https://ms.wordpress.org/plugins/hafenstudios-ads/#developers)

 [Support](https://wordpress.org/support/plugin/hafenstudios-ads/)

## Description

Hafenstudios Ads is an ad manager for WordPress: place banner ads, AdSense units
and any ad code exactly where you want them, rotate them, target who sees them, 
and keep an eye on impressions, clicks and CTR — without sending any analytics to
an external server.

Create multiple ad blocks, insert them automatically before or after the content,
after paragraph N or by shortcode, widget and Gutenberg block. Weighted ad rotation,
device and post-type targeting, campaign scheduling and consent gating are built
in. Part of the hafenstudios plugin family.

#### Highlights

 * Clean, focused admin interface with brand bar, weekly summary and clear navigation
   tabs.
 * Automatic placements before content, after content, after paragraph N or after
   the first image.
 * Manual placement via shortcode `[adjet_ad id="1"]`, widget or Gutenberg block.
 * Weighted ad rotation for blocks sharing a group name: in automatic placements
   and via `[adjet_ad_group name="header"]`, decided in the browser so it stays 
   fair behind page caches.
 * Split test view for one rotation group: every variant with impressions, clicks
   and CTR, and a mark on the one that is ahead.
 * Device targeting for desktop, tablet and mobile.
 * Post type targeting plus exclusions for posts, categories, tags and custom terms.
 * Optional “Advertisement” label with editable text.
 * Lazy loading via IntersectionObserver.
 * Consent-cookie gating for common consent tools.
 * Optional anonymous local impression and click statistics.
 * Campaign scheduling with optional start and end time.
 * One-click duplicate and pause/activate actions for faster workflow.
 * Code editor and admin-side live preview that does not execute scripts.
 * AdSense Wizard: Publisher-ID + Slot-ID are enough for responsive AdSense units.
 * Optional AdSense Auto Ads script loader with clear settings.
 * 30-day statistics chart (impressions and clicks) rendered inline, no external
   libraries.
 * Weekly summary above the ad block list: impressions, clicks and CTR since Monday,
   compared with the same weekday span of the previous week.
 * Least-privilege capability `manage_adjet` with an optional editor-access toggle.
 * Template gallery with ready-to-use banners, notification bars and popups; premium
   templates unlock with Pro.
 * REST API (`adjet/v1`) for ad blocks, stats and settings via Application Passwords.
 * Guided assistant with optional AI copy suggestions (bring your own Anthropic 
   Claude key).
 * Built-in cookie-consent banner template with Google Consent Mode v2 support.
 * Native newsletter opt-in for SendFox, MailerLite, Brevo, Mailchimp and Kit (ConvertKit),
   bring your own token, with double opt-in.
 * First-run onboarding that routes you to AdSense, a template or your own HTML.
 * JSON import and export with file-size/type checks.
 * Uninstall routine that keeps your data unless you explicitly ask for it to be
   deleted.

#### Privacy

The plugin does not contact hafenstudios servers from the WordPress admin area or
frontend. Optional statistics are stored locally in your own WordPress database.
Third-party ad code pasted into an ad block may contact external services; configure
your consent solution accordingly.

#### External services

The plugin works fully without any external service. Every integration below is 
optional and only ever runs when you explicitly enable it:

 * Google AdSense (frontend): if you configure an AdSense ad unit or enable Auto
   Ads, the frontend loads Google’s `adsbygoogle.js` from `pagead2.googlesyndication.
   com` to display ads. Terms: https://www.google.com/adsense/localized-terms — 
   Privacy: https://policies.google.com/privacy
 * Anthropic Claude (admin only, bring-your-own-key): the optional AI buttons send
   data to the Anthropic API (`api.anthropic.com`), each only after you enter your
   own Anthropic API key in the settings and click that button; no key, no request,
   never automatic. What each button sends: the “AI suggestions” button in the ad
   assistant sends the template’s field labels, your site name/description and any
   brief you type to generate draft ad copy; the “Suggest alt text” button sends
   the selected ad image (from your media library as encoded image data, otherwise
   as its URL) to describe it; the “Let the AI read the numbers” button on the statistics
   page sends aggregated daily totals, weekly totals and per-block impression/click
   counts. No visitor data, IP addresses or e-mail addresses are ever sent. The 
   key is stored encrypted and used server-side only. Terms: https://www.anthropic.
   com/legal/commercial-terms — Privacy: https://www.anthropic.com/legal/privacy
 * SendFox (bring-your-own-token): if you connect SendFox in the settings and use
   the “Newsletter (SendFox)” template, visitor email addresses submitted through
   that form are sent to the SendFox API (`api.sendfox.com`) to be added to your
   list. This happens only when you have connected a SendFox access token. The token
   is stored encrypted and used server-side only. Terms: https://sendfox.com/tos—
   Privacy: https://sendfox.com/privacy
 * MailerLite (bring-your-own-token): if you connect MailerLite in the settings 
   and use the “Newsletter (MailerLite)” template, visitor email addresses submitted
   through that form are sent to the MailerLite API (`connect.mailerlite.com`) to
   be added to your group. This happens only when you have connected a MailerLite
   API token. The token is stored encrypted and used server-side only. Terms: https://
   www.mailerlite.com/legal/terms-of-service — Privacy: https://www.mailerlite.com/
   legal/privacy-policy
 * Brevo (bring-your-own-token): if you connect Brevo in the settings and use the“
   Newsletter (Brevo)” template, visitor email addresses submitted through that 
   form are sent to the Brevo API (`api.brevo.com`) to be added to your list. This
   happens only when you have connected a Brevo API key. The key is stored encrypted
   and used server-side only. Terms: https://www.brevo.com/legal/termsofuse/ — Privacy:
   https://www.brevo.com/legal/privacypolicy/
 * Mailchimp (bring-your-own-token): if you connect Mailchimp in the settings and
   use the “Newsletter (Mailchimp)” template, visitor email addresses submitted 
   through that form are sent to the Mailchimp API (`<dc>.api.mailchimp.com`, the
   data center encoded in your API key) to be added to your audience with status“
   pending”, which triggers Mailchimp’s double opt-in. This happens only when you
   have connected a Mailchimp API key. The key is stored encrypted and used server-
   side only. Terms: https://mailchimp.com/legal/terms/ — Privacy: https://www.intuit.
   com/privacy/statement/
 * Kit, formerly ConvertKit (bring-your-own-token): if you connect Kit in the settings
   and use the “Newsletter (Kit)” template, visitor email addresses submitted through
   that form are sent to the Kit API (`api.kit.com`) to create or update the subscriber
   and add them to your chosen Kit form; if the form has double opt-in enabled, 
   Kit sends its confirmation email. This happens only when you have connected a
   Kit v4 API key. The key is stored encrypted and used server-side only. Terms:
   https://kit.com/terms — Privacy: https://kit.com/privacy

#### Security

The plugin uses capability checks, nonces for form actions, sanitization on save
and escaping on output. Raw ad code is only stored unchanged for users with the `
unfiltered_html` capability.

#### Localization

 * Source language: English.
 * Included translations: German, Spanish, French and Dutch — complete and shipped
   with the plugin.

#### Support

This plugin is developed and maintained by hafenstudios. For direct support you 
can reach us by e-mail at moin@hafenstudios.com or by phone at +49 174 3935796. 
You are also welcome to use the plugin support forum on WordPress.org.

## Screenshots

[⌊The ad blocks overview with impressions, clicks and CTR per block.⌉⌊The ad blocks
overview with impressions, clicks and CTR per block.⌉[

The ad blocks overview with impressions, clicks and CTR per block.

[⌊The template gallery: pick a purpose, fill in the fields, no HTML needed.⌉⌊The
template gallery: pick a purpose, fill in the fields, no HTML needed.⌉[

The template gallery: pick a purpose, fill in the fields, no HTML needed.

[⌊The guided editor with live preview while you type.⌉⌊The guided editor with live
preview while you type.⌉[

The guided editor with live preview while you type.

[⌊The AdSense assistant: Publisher-ID, slot and format, nothing else.⌉⌊The AdSense
assistant: Publisher-ID, slot and format, nothing else.⌉[

The AdSense assistant: Publisher-ID, slot and format, nothing else.

[⌊Placement options, device targeting and consent gating for a single block.⌉⌊Placement
options, device targeting and consent gating for a single block.⌉[

Placement options, device targeting and consent gating for a single block.

[⌊Local statistics with the 30-day chart, rendered server-side without any external
service.⌉⌊Local statistics with the 30-day chart, rendered server-side without any
external service.⌉[

Local statistics with the 30-day chart, rendered server-side without any external
service.

## Blocks

This plugin provides 1 block.

 *   Adjet Ad

## Installation

 1. Upload the ZIP via Plugins > Add New > Upload Plugin.
 2. Activate the plugin.
 3. Open the new “Hafenstudios Ads” menu and create your first ad block.
 4. Optional: configure the ad label, consent-cookie settings and local statistics.

Upgrading from “AdEngine – Free Ad Inserter & Manager”? Just install this plugin—
your ad blocks, settings and statistics are migrated automatically on first load.

## FAQ

### Does this plugin work with AdSense?

Yes. You can either paste original AdSense code as custom code or use the AdSense
Wizard with your Publisher-ID and Slot-ID. The plugin then generates a responsive
ad unit and loads the AdSense script on the frontend when needed.

### Can I use it manually?

Yes. Use the shortcode `[adjet_ad id="1"]`, the shortcode `[adjet_ad_group name="
header"]`, the included widget or the Gutenberg block.

### Does it replace a consent tool?

No. The plugin can wait for a configured consent cookie, but it does not provide
legal advice or a cookie banner.

### Does this plugin track users externally?

No. The optional statistics feature stores anonymous aggregated counts locally in
your WordPress database.

### Does the AI feature send data anywhere?

Only when you use it. The AI is the one deliberate exception to “no external calls”:
it runs only after you store your own Anthropic API key and click a button – one
click, one request, never automatic. Depending on the button, the request carries
the template’s field labels, your site name and description, the brief you type,
the selected ad image (alt-text suggestion) or aggregated statistics totals (statistics
summary). It never sends visitor data, IP addresses, e-mail addresses or page content,
and your key is stored encrypted and never leaves your server.

### Can editors manage ads without being administrators?

Yes. Enable “Editor access” in Settings to grant the `manage_adjet` capability to
the editor role. Administrators always have access.

### What happens to my data when I uninstall the plugin?

Nothing is deleted unless you ask for it. The setting “Delete all data on uninstall”
is off by default, so removing the plugin leaves your ad blocks, settings and the
statistics table in place and a later reinstall picks them up again. Switch the 
setting on before uninstalling if you want the options, the statistics table and
the `manage_adjet` capability removed for good.

### Is there a REST API?

Yes. The `adjet/v1` namespace exposes ad blocks (`/blocks`, CRUD), statistics (`/
stats`) and settings (`/settings`). Authenticate with an Application Password; access
requires the `manage_adjet` capability.

## Reviews

![](https://secure.gravatar.com/avatar/45fa9321a4607ec572da81465c67f4c663ef7690d3ced50abd4e248f522ebc49?
s=60&d=retro&r=g)

### 󠀁[Powerful free ad tool](https://wordpress.org/support/topic/powerful-free-ad-tool/)󠁿

 [rokrking](https://profiles.wordpress.org/rokrking/) 14 Ogos 2026

An excellent experience using this plugin for my niche site. Setting up Adsense 
is too simple.

![](https://secure.gravatar.com/avatar/36bd255c7dd04fd1b37b20c995d716f330f4e96e36507259d5f54cbf897ac6f6?
s=60&d=retro&r=g)

### 󠀁[Nice 4 managing ads](https://wordpress.org/support/topic/nice-4-managing-ads/)󠁿

 [papkeconsulting](https://profiles.wordpress.org/papkeconsulting/) 13 Ogos 2026

This Plugin ist Nice for managing ads in wordpress

![](https://secure.gravatar.com/avatar/f3b6fb798798482e05617c9e855a028484c42c60f7c16501cb7e7c81bbab2563?
s=60&d=retro&r=g)

### 󠀁[Useful, smart, elegant ads-tool](https://wordpress.org/support/topic/useful-smart-elegant-ads-tool/)󠁿

 [spielstratege](https://profiles.wordpress.org/spielstratege/) 12 Ogos 2026

Very powerful features – split testing works great – very clean and effective design.
Developer is very helpful and engaged. The other plugins are also worth a look!

![](https://secure.gravatar.com/avatar/d426c44ec01fa9e9654ba22dca771c7a3232b295b0826eead847bdbe1467dc96?
s=60&d=retro&r=g)

### 󠀁[Super helpful](https://wordpress.org/support/topic/super-helpful-177/)󠁿

 [leonde123](https://profiles.wordpress.org/leonde123/) 12 Ogos 2026

I used the Plugin for some days. I’m very content about the usability. Thanks for
the free plugin!!

![](https://secure.gravatar.com/avatar/9347cf53cc1a0e54d24715ca392bb488da7d775565e9eee59667d45667bde408?
s=60&d=retro&r=g)

### 󠀁[Great interface, powerful features](https://wordpress.org/support/topic/great-interface-powerful-features/)󠁿

 [arcrider](https://profiles.wordpress.org/arcrider/) 12 Ogos 2026

As a UI/UX designer and product manager at Arc Rider Ventures, I always look at 
the interface of WordPress plugins first and Hafenstudios Ads is a real highlight
here. The backend is extremely clean, and features like device targeting, cookie
consent gating, and local statistics are solved super intuitively. Finally, an ads
plugin that hits the perfect balance between feature richness and simplicity. Well-
deserved 5 stars!

![](https://secure.gravatar.com/avatar/f7f5427cb5fca3fe8b86ce075c790ac834f5d8ac9ab0a48691fa26c45debdb91?
s=60&d=retro&r=g)

### 󠀁[Big fan of privacy-focus](https://wordpress.org/support/topic/big-fan-of-privacy-focus/)󠁿

 [twofingersapps](https://profiles.wordpress.org/twofingersapps/) 12 Ogos 2026

Was looking for a plugin like this a while already. Everything else is cloud-based
and heavily limited to sell subscriptions – refreshing to see a plugin do the exact
opposite: Provide value without selling your data and not even pushing a paid plan
all the time. Keep it up!

 [ Read all 10 reviews ](https://wordpress.org/support/plugin/hafenstudios-ads/reviews/)

## Contributors & Developers

“Hafenstudios Ads – Ad Manager, AdSense & Banner Ads” adalah perisian sumber terbuka.
Orang-orang berikut telah menyumbang kepada pemalam ini.

Penyumbang

 *   [ hafenstudios ](https://profiles.wordpress.org/hafenstudios/)

“Hafenstudios Ads – Ad Manager, AdSense & Banner Ads” telah diterjemahkan ke dalam
1 penempatan. Terima kasih kepada [para penterjemah](https://translate.wordpress.org/projects/wp-plugins/hafenstudios-ads/contributors)
untuk terjemahan mereka.

[Translate “Hafenstudios Ads – Ad Manager, AdSense & Banner Ads” into your language.](https://translate.wordpress.org/projects/wp-plugins/hafenstudios-ads)

### Berminat dalam pembangunan?

[Layari kod](https://plugins.trac.wordpress.org/browser/hafenstudios-ads/), periksa
[repositori SVN](https://plugins.svn.wordpress.org/hafenstudios-ads/), atau langgani
[log pembangunan](https://plugins.trac.wordpress.org/log/hafenstudios-ads/) dengan
[RSS](https://plugins.trac.wordpress.org/log/hafenstudios-ads/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 2.2.0

 * New: a “Split-Tests” page that reads one of your rotation groups as an A/B test.
   Ad blocks sharing a group name have been rotating and counting per block for 
   a while, but nowhere could you see the variants side by side. The page lists 
   every variant of the group with its status, weight, impressions, clicks and CTR,
   and marks the one that is ahead. Nothing new is measured, nothing is sent anywhere,
   and no API key of any kind is involved.
 * “Ahead right now” appears only once two running variants have at least 100 impressions
   each in the selected period and their rates actually differ. One variant over
   the threshold while the other has three impressions names nobody, and neither
   does a tie. The size of the lead is printed underneath in percentage points, 
   because a lead of one single click looks exactly like a lead of five points otherwise.
   Whether that lead will hold is a question of significance, which is what Pro 
   answers, together with the uplift, taking the winner over with one click and 
   an AI suggestion for the next variant.
 * A group counts as a test when its blocks share a group name AND a placement. 
   That is how the rotation works: in automatic placements only blocks with the 
   same placement take turns, everything else appears on the page at the same time.
   Two blocks of one group in different placements are therefore not competing, 
   and putting them side by side as variants would compare positions rather than
   variants. The shortcode `[adjet_ad_group name="header"]` is unaffected, it rotates
   the whole group, and those blocks all carry the placement “manual”.
 * You can run as many rotation groups as you like, as always. One of them is evaluated
   on the page, and you pick which one with a single click. Without a pick it is
   the test you created first, which cannot move under you when a group is renamed.
 * Rotation groups that contain a cookie banner are shown but not judged: the banner’s
   buttons set a cookie instead of counting as a click, so its CTR would report 
   a perfectly good banner as the loser. The page says so instead of pretending 
   otherwise.
 * Paused variants stay in their group with their numbers, so pausing one does not
   delete half the test from view. They cannot be “ahead right now”, though: a variant
   that is not being served is not running against anything, and its numbers stop
   while the others keep counting.
 * Changed, please read this one: an address that is already on your newsletter 
   list now gets exactly the same confirmation as a brand new one. Until now the
   form printed the answer of your newsletter provider word for word, and that answer
   says out loud whether an address is already a member. Anyone could have typed
   addresses into your form one after another and read off who is on your list. 
   The form no longer tells the two cases apart at all, which is also all that a
   provider with double opt-in reveals to the outside. What that costs you: a visitor
   who mistypes and hits someone else’s address still reads “please confirm your
   signup”. The message now means “we handed this over to your provider”, not “this
   address is new”.
 * Fixed: the signup form no longer shows a single word written by your newsletter
   provider. Whatever SendFox, MailerLite, Brevo, Mailchimp or Kit answers stays
   on your server. Visitors read your own sentence, in the language of your site,
   instead of an English developer message such as “is already a list member. Use
   PUT to insert or update list members.”
 * Fixed: connection problems no longer put technical detail in front of visitors.
   A failed lookup used to show the cURL error and the host name of your provider
   inside the form.
 * Changed: the same neutral answer covers every rejection your provider sends back
   about a submission, not only the two status codes Mailchimp happens to use for
   a duplicate. A rule that neutralises 400 and 422 alone re-opens the same hole
   the day a provider answers “already a member” with 409 instead. The deliberate
   price: a genuinely broken setup, for example a required merge field your form
   does not send or a list deleted at the provider, now also looks like a success
   from the front. That is why every one of those cases is written to the log described
   below and shown as a warning on the ad block overview. Throttling by your provider(
   429), a provider outage and a rejected token stay errors, because none of them
   depend on the address that was entered.
 * Fixed: the status code of the signup endpoint now says what actually happened.
   Everything the provider answers about a submission is a normal 200. There are
   three error states and they mean what they say: 503 the provider answered but
   cannot deliver right now, 502 the request never reached the provider at all, 
   and 500 something in your own setup is wrong (no token, no list picked, token
   rejected) and will not fix itself by waiting. If you monitor 502 responses, expect
   them to nearly disappear.
 * New: the ad block overview shows the last signup that did not go through, with
   the date, the provider, the status code and the provider’s own words. That is
   where the detail went that visitors no longer see, so a broken connection cannot
   stay hidden behind a friendly confirmation. E-mail addresses in that message 
   are masked. The duplicate case is deliberately not listed there: it is not a 
   failure, it is the most frequent thing that happens to a public form, and it 
   would push the rare configuration error out of that single slot.
 * Fixed: with Kit, an address that was already known could end the signup halfway.
   Kit is told about the subscriber first and only then about the form, and only
   that second step sends the confirmation mail. A known address stopped the first
   step, so the visitor got an error and no mail. Both steps now run, and a real
   problem in that first step is written to the log instead of disappearing. Kit’s
   own wording arrives there too: Kit reports its reasons in a field the plugin 
   did not read, so every Kit problem used to be logged as a bare status code.
 * Fixed for Brevo: a signup with an address Brevo already had would quietly add
   that person to the list you configured, including someone who had unsubscribed
   from exactly that list, and Brevo sends no confirmation mail at this step. The
   plugin no longer updates existing contacts. New contacts are created as before,
   and a known address is answered by Brevo with an error that counts as a success
   towards the visitor, so nothing changes for them.
 * Fixed: the honeypot answer. A submission caught by the hidden anti-bot field 
   was answered with a slightly different body than a real signup, which made the
   trap detectable in a single request. Both answers are now byte for byte identical.
 * Fixed: the three fallback texts of the signup form (“Thank you!”, “Something 
   went wrong.”, “Connection failed. Please try again later.”) were built into the
   JavaScript file and could never be translated. They now come from the server,
   translated like every other text.

#### 2.1.1

 * Fixed: a period now covers exactly as many days as it says. The totals below 
   the chart reached one day further back than the chart itself, so “30 days” added
   up 31 days and “7 days” added up 8. Impressions, clicks and CTR now always cover
   today plus the days before it, and the table finally matches the curve above 
   it. Because of that, all reported numbers drop slightly once, by roughly one 
   day’s worth: around 3 % over 30 days, around an eighth over 7 days. No data was
   lost, the oldest day simply no longer belongs to the period. Give it five minutes
   after the update, the statistics are cached that long.
 * Fixed: deleting an ad block no longer hands its number to the next one. A newly
   created or duplicated block could be given the number of a deleted block, and
   it started out with that block’s impressions and clicks. Worse, every `[adjet_ad
   id="7"]` still sitting in an old post or a widget quietly began showing the new
   ad instead of showing nothing. Numbers are now handed out once and only ever 
   count upwards. Existing blocks keep their numbers, existing shortcodes keep pointing
   where they always did.
 * Fixed: importing ad blocks with “Replace existing ad blocks” no longer restarts
   the numbering at 1, so imported blocks no longer take over the statistics and
   the shortcodes of the blocks they replaced. Reading your own export back into
   the same site stays lossless: replacing keeps the numbers stored in the file,
   so the shortcodes in your content keep working. Blocks imported on top of your
   existing ones get fresh numbers, as they always did.
 * Fixed: “Top block” in the weekly summary could be won by an ad block that has
   been deleted. The line then vanished completely, because the block list no longer
   holds that number, and the strongest block you still have was never named. Only
   blocks that still exist take part now, and the weekly summary is rebuilt the 
   moment you add, rename, delete or import a block instead of waiting up to 15 
   minutes for its cache to expire.
 * Fixed: the week card no longer shows a green upwards arrow for a decline. A drop
   of 0.04 % rounds to 0.0 % and got the arrow anyway. Unchanged is now a state 
   of its own: an arrow to the side, in the muted colour of the card.
 * Fixed: a click-through rate is no longer printed as 0.00 % when clicks were counted
   without a single impression, which happens when a blocker or a cache swallows
   the impression. Those cells now read “n/a”, because an unknown rate is not a 
   rate of zero. No clicks on no impressions stays 0.00 %.
 * Fixed: the AI statistics summary was handed the click-through rate with a decimal
   point no matter what language your site speaks, and quoted it back that way in
   an otherwise German answer. Numbers now go into the briefing formatted for the
   site language.
 * Importing ad blocks with “Append” now books all block numbers in a single write
   instead of one write per block. The numbers themselves, and the order they are
   handed out in, stay exactly the same.
 * Ready for WordPress 7.1: the editor block now registers with block API version
   3. WordPress 7.1 always runs the post editor inside an iframe and warned in the
   browser console that a block on version 2 could force the editor back into its
   old mode. The block’s placeholder also gets its own editor stylesheet, because
   the admin stylesheet never reached the editor canvas and the placeholder was 
   drawn there without any styling at all.
 * The plugin now carries the same name in the plugin list as in the WordPress.org
   directory. The two had drifted apart, which the directory flags on every single
   update.
 * The recorded impressions and clicks of a deleted block stay where they are, on
   purpose. They still count towards this week’s totals and the milestones, because
   that traffic did happen and there is no way to bring it back once it is gone.
   Nothing is deleted unless you switch on “Delete all data on uninstall”.

#### 2.1.0

 * Ad rotation is now cache-proof and works in automatic placements: blocks sharing
   a group name render into one rotation container and the browser picks the weighted
   winner before any impression is counted. Previously rotation only existed in 
   the `[adjet_ad_group]` shortcode, froze behind page caches, and two grouped blocks
   with the same automatic placement appeared side by side instead of rotating.
 * Without JavaScript the first variant of a group is shown, so rotation groups 
   fail open.
 * Impressions are now counted when an ad actually becomes visible (at least half
   of it inside the viewport) instead of as soon as the page loads, and ads hidden
   via CSS are never counted. Expect lower impression numbers and a correspondingly
   higher CTR than in 2.0.0 – that is intentional and makes rotation groups measure
   copy quality instead of layout position.
 * AI suggestions now write the ad copy in your site language instead of defaulting
   to English.
 * Overlays and popups now respect content targeting on single posts and pages: “
   show only in categories/tags”, excluded terms and excluded posts apply there,
   and a filled “show only in” list keeps the overlay off home, archive and search
   pages. Empty targeting fields keep the overlay site-wide, exactly as before.
 * Two new AdSense formats in the wizard and the AdSense template: In-article (fluid)
   and Multiplex (related content grid) – the native formats blogs use inside their
   content.
 * New free template “Text link / paragraph ad”: a sponsored short paragraph in 
   your content’s look with labelling and a `rel="sponsored"` text link.
 * New free template “Coupon box”: an inline deal box whose coupon code visitors
   copy with one click, plus a button to the offer.
 * New Pro template in the gallery: review box with star rating and pros/cons list.
 * Kit (formerly ConvertKit) joins as the fifth newsletter provider: connect your
   Kit v4 API key and the “Newsletter (Kit)” template subscribes visitors to the
   Kit form of your choice; Kit’s own double opt-in applies.
 * Claude Opus 5 is the new default AI model; Opus 4.8, Sonnet 5 and Haiku 4.5 stay
   available and stored model choices keep working. Answers that hit the token limit
   now show a clear “cut off, please retry” message instead of a JSON error.
 * New “Test connection” button next to the stored Claude key, a status badge on
   the AI settings section, relative cost hints per model and a monthly usage counter(
   calls and tokens) with a link to your Anthropic console.
 * Without a stored key, the assistant now shows a static example of how the AI 
   would fill the fields – clearly labelled as an example, no API call involved.
   A one-time dismissible card points to the feature.
 * New AI alt-text suggestion for the image banner: one click sends the ad image
   to Anthropic via your own key and returns an editable image description.
 * New AI statistics summary on the statistics page: aggregated totals of the last
   30 days go to Anthropic via your own key and come back as a short interpretation
   with one recommendation – including the context that 2.1.0 counts impressions
   on visibility, so lower numbers are expected.
 * The settings and the readme now spell out per AI button what is transferred and
   what never is (no visitor data, no IP addresses, no e-mail addresses, no page
   content).
 * Translated all new texts into German (informal and formal), Spanish, French, 
   Italian, Dutch and Brazilian Portuguese. The formal German catalog also caught
   up on the strings it was missing from earlier releases.
 * Choose your Cookie: the consent banner template can now show one of four bundled
   cookie images next to the text (flat, mascot, monoline, realistic) – picked from
   preview cards in the wizard. Decorative, lightweight WebP, and existing banners
   stay image-free until you pick a style. Five more styles plus a custom image 
   option come with Pro.
 * The cookie consent banner template moved up in the template gallery: it now sits
   right behind the core ad formats, so it lands in the wizard’s first visible row.
   Pure catalog order, existing blocks are untouched.
 * Fixed: overlays and popups ignore the lazy loading option. Lazy loading kept 
   the markup in a `<template>` until the block’s wrapper scrolled into view, but
   an overlay is fixed to the window edge while its wrapper sits in the content 
   flow – so the cookie banner could appear late, at a random scroll position, or
   never at all on short pages. Overlays now render immediately; inline ads keep
   lazy loading unchanged.
 * Fixed: overlay impressions are counted when the overlay itself becomes visible.
   The visibility check watched the block’s wrapper, but an overlay’s wrapper is
   an empty element left behind in the content flow – at the very end of the document
   for footer-rendered overlays – so overlay impressions were only booked once a
   visitor scrolled all the way down.
 * The statistics page previews the Pro consent statistics as a locked row (consent
   rate of your cookie banner, daily aggregates per block, no cookies and no visitor
   data). The upgrade page now also mentions consent banner A/B tests measured by
   consent rate and geo-varied banners (e.g. strict for the EU, slim elsewhere).

#### 2.0.0

 * New free placement “Between posts”: show an ad in blog, archive and search listings
   after every Nth post.
 * New free templates: image banner, HTML/code tile, sticky bottom bar (anchor ad),
   countdown banner (hides itself after expiry), social follow bar and a sponsored-
   content disclosure note.
 * New Pro templates in the gallery: slide-in box (default trigger 50% scroll depth),
   recommendation card in post style, product/affiliate box with mandatory labelling,
   Google Ad Manager slot, video ad, comparison box, ad slider and content locker
   light.
 * New Pro targeting (in Adjet Pro): referrer targeting and weekday/hour time windows,
   both evaluated in the browser so they stay correct behind page caches.
 * New targeting: “Show only in categories/tags” complements the existing exclusion
   list.
 * Cache-proof statistics: tracking no longer requires an expiring nonce (protected
   by an event whitelist, block-ID checks and an IP rate limit instead), and impressions
   are bundled into one beacon per page.
 * The AdSense loader now only loads on pages that actually serve an AdSense block–
   with consent gating, only after consent has been given. The frontend stylesheet
   is now inlined in the head (0.7 KB, no extra request).
 * One shared guard for shortcode, widget and Gutenberg block: ended campaigns no
   longer keep running through the Gutenberg block.
 * Honesty: removed the never-implemented template teasers “Spin-to-Win” and “Reader
   paywall”, including their claims on the upgrade page.
 * Correctness: UTF-8 word counting for the minimum word count, save errors now 
   show as an error notice instead of “saved”, and a new index on stat_date speeds
   up the statistics.
 * Hardening: the Cloudflare IP header only counts for rate limiting when the ADJET_BEHIND_CF
   constant is set explicitly; the newsletter opt-in no longer requires a nonce 
   that broke on page-cached sites.
 * New in the plugins list: a “Manage ads” button and a rate-this-plugin link.

#### 1.9.0

 * Added three more newsletter providers next to SendFox: MailerLite, Brevo and 
   Mailchimp. Each one has its own template and its own connection, so you can run
   several at once and pick a different list per ad block.
 * Every provider token is stored encrypted on its own, so connecting a new provider
   never touches an existing one. An already connected SendFox account keeps working
   unchanged after the update.
 * Mailchimp signups are handed over with status “pending”, which triggers Mailchimp’s
   own confirmation mail.
 * Uninstalling now also removes the tokens and cached lists of the new providers.
 * Translated all new texts into German, Spanish, French, Dutch, Italian and Portuguese.
 * Fixed: the click-through rate now follows the site language. On a German site
   it read “1.58” right next to “31.847” impressions, where the dot is a thousands
   separator – two different meanings for the same character.

#### 1.8.7

 * Added a small card above the content of the plugin’s own pages that shows one
   thing at a time: a statistics milestone, a one-off review request, or a feature
   you may not have found yet. Never more than one card, never on other pages of
   the admin area, and every card can be dismissed for good.
 * Replaced the four 30-day tiles above the ad block list with a weekly summary:
   impressions, clicks and CTR since Monday, compared with the same weekday span
   of the previous week, plus a 7-day chart and the strongest ad block of the week.
   Same local data as before, nothing new is collected.
 * Added the setting “Delete all data on uninstall”, switched off by default. Until
   you switch it on, removing the plugin leaves your ad blocks, settings and statistics
   untouched.
 * The assistant now states plainly what your own Claude API key unlocks, and the
   settings explain that requests go from your site straight to Anthropic with your
   own account.
 * Added complete Spanish, French and Dutch translations and completed the German
   one.
 * Added a link to the manual on the plugin pages.

#### 1.8.6

 * Fixed: the Pro page named the wrong payment provider. Purchases are handled by
   Freemius, not Digistore24; the 30-day money-back guarantee is unchanged.

#### 1.8.5

 * The plugin now speaks English by default: all source strings were translated 
   from German to English, and German ships as a complete translation that loads
   automatically on German sites. Before this release, every site saw the German
   interface regardless of its language.
 * Removed the broken placeholder translation files (en/es/fr/nl) that did not actually
   translate anything; Spanish, French and Dutch will return via wordpress.org language
   packs.
 * Added the six directory screenshots.

#### 1.8.4

 * Renamed the plugin to “Hafenstudios Ads – Ad Placement Manager” and changed the
   text domain to `hafenstudios-ads`, following the WordPress.org plugin review.
   No functional changes.
 * Internal prefixes, option names, shortcodes and the REST namespace are deliberately
   unchanged, so existing ad blocks, settings and statistics keep working.

#### 1.8.2

 * Removed the legacy `[sai_ad]` and `[sai_ad_group]` shortcode aliases, so every
   public name this plugin registers now carries the `adjet` prefix. Use `[adjet_ad]`
   and `[adjet_ad_group]` instead.
 * The Google AdSense loader is now enqueued with `wp_enqueue_script()` only; the
   custom script-tag filter that added the optional `crossorigin` attribute has 
   been dropped.
 * Documented the output escaping contract of the ad render pipeline directly at
   the shortcode, block and `the_content` callbacks.

#### 1.8.1

 * Fixed the Plugin URI and the SendFox terms link so all declared URLs resolve.
 * Moved all frontend and admin JavaScript and CSS out of inline `<script>`/`<style
   >` tags into properly enqueued files: base styles now load as `public/frontend.
   css`, the AdSense unit call, the popup/exit-intent/cookie-consent behaviour and
   the admin live preview run from enqueued scripts. No behaviour change.
 * Hardened and documented output escaping around the ad render pipeline (generated
   markup is escaped; raw custom code stays gated behind the `unfiltered_html` capability,
   like the core Custom HTML block).
 * Switched all direct database access to prepared statements using the `%i` table-
   identifier placeholder, which raises the minimum WordPress version to 6.2.

#### 1.8.0

 * Added a built-in Cookie-Consent banner template: visitors accept or decline, 
   it sets the consent signal your consent-gated ads wait for, and it emits Google
   Consent Mode v2 updates. No separate consent plugin needed.
 * Added a native SendFox newsletter integration (bring your own SendFox access 
   token): the new “Newsletter (SendFox)” template subscribes visitors straight 
   into your chosen list. SendFox handles the double opt-in.
 * Added a public opt-in endpoint protected by nonce, honeypot and rate limiting;
   the token is stored encrypted and used server-side only.
 * Generalised the assistant with a third mapper type (provider) so more email providers
   can hook in later.

#### 1.7.0

 * Added a template gallery with ready-to-use ads, banners, notification bars and
   popups (free), plus Pro-badged premium templates and a Free/Pro foundation with
   an upgrade page. Free stays fully functional.
 * Added a guided assistant: pick a template and just fill in fields (title, text,
   link, colour) with a live preview instead of writing HTML. Field values are stored
   and stay editable; “HTML selbst bearbeiten” switches to the raw editor.
 * Added a guided Google AdSense assistant: enter Publisher-ID, Slot-ID and format,
   and the plugin builds the responsive unit.
 * Added optional AI copy suggestions in the assistant: bring your own Anthropic
   Claude API key and let the AI draft titles, texts and button labels as fully 
   editable suggestions. One request per click, never automatic; the key is stored
   encrypted (libsodium) and used server-side only.
 * Added a site-wide “overlay” placement so popups, exit-intent and notification
   bars display and self-trigger.
 * Added a first-run onboarding panel that routes you to AdSense, a template or 
   your own HTML.
 * Refined the admin: save-in-editor confirmation, compact icon actions, a collapsible“
   Erweitert” section, and Hans, the hand-drawn hafenstudios captain mascot.

#### 1.6.0

 * Added a least-privilege capability `manage_adjet` (administrators keep access
   via a manage_options fallback) plus an optional editor-access toggle in Settings.
 * Added a REST API under `adjet/v1` for ad blocks, statistics and settings (Application
   Password auth).
 * Added a 30-day impressions/clicks chart to the statistics page, rendered inline
   as SVG without external libraries.

#### 1.5.0

 * Rebranded the plugin as part of the hafenstudios plugin family.
 * Redesigned the admin interface in the clean hafenstudios/Linkjet design language(
   brand bar, tab navigation, teal accent, KPI and content cards).
 * Migrated shortcodes to `[adjet_ad]` and `[adjet_ad_group]`; the legacy `[sai_ad]`/`[
   sai_ad_group]` shortcodes keep working as aliases.
 * Automatic data migration from a previous AdEngine install (ad blocks, settings
   and statistics).
 * Added object-cache-backed statistics totals to reduce database load.
 * Fixed AdSense script enqueue to always carry a version and cleaned up Plugin 
   Check notices.

#### 1.4.3

 * Renamed the public plugin title to comply with WordPress.org naming restrictions.

#### 1.4.1

 * Refined admin interface with cleaner hero, glass navigation, stronger cards and
   better responsive behavior.
 * Improved backend usability, visual hierarchy and AdSense onboarding cues.

#### 1.4.0

 * Added AdSense Wizard for easy responsive AdSense ad units using Publisher-ID 
   and Slot-ID.
 * Added optional AdSense Auto Ads frontend loader.
 * Added dynamic Gutenberg block for manual placements.
 * Added weighted ad rotation groups.

#### 1.3.1

 * Added campaign scheduling with optional start/end time.
 * Added one-click duplicate and pause/activate actions.
 * Added automatic placement after the first image.
 * Added WordPress code editor integration and a safer admin-side live preview.

#### 1.3.0

 * Added optional local statistics toggle.
 * Hardened import flow with JSON extension and file-size validation.
 * Improved security posture around raw ad code.

#### 1.2.0

 * Added backend styling with hero area and KPI cards.
 * Added localization starter files.

#### 1.1.0

 * Added label, AMP exclusion, server-side device detection, minimum word count,
   max-per-post, exclusion lists, lazy loading, consent gating, stats, import/export
   and uninstall routine.

#### 1.0.0

 * Initial version.

## Meta

 *  Version **2.2.0**
 *  Last updated **16 jam lalu**
 *  Active installations **40+**
 *  WordPress version ** 6.2 or higher **
 *  Tested up to **7.1**
 *  PHP version ** 7.4 or higher **
 *  Languages
 * [English (US)](https://wordpress.org/plugins/hafenstudios-ads/) dan [German](https://de.wordpress.org/plugins/hafenstudios-ads/).
 *  [Terjemahkan kepada bahasa anda](https://translate.wordpress.org/projects/wp-plugins/hafenstudios-ads)
 * Tags
 * [ad manager](https://ms.wordpress.org/plugins/tags/ad-manager/)[ads](https://ms.wordpress.org/plugins/tags/ads/)
   [adsense](https://ms.wordpress.org/plugins/tags/adsense/)[advertising](https://ms.wordpress.org/plugins/tags/advertising/)
   [banner ads](https://ms.wordpress.org/plugins/tags/banner-ads/)
 *  [Paparan Lanjutan](https://ms.wordpress.org/plugins/hafenstudios-ads/advanced/)

## Ratings

 5 out of 5 stars.

 *  [  10 5-star reviews     ](https://wordpress.org/support/plugin/hafenstudios-ads/reviews/?filter=5)
 *  [  0 4-star reviews     ](https://wordpress.org/support/plugin/hafenstudios-ads/reviews/?filter=4)
 *  [  0 3-star reviews     ](https://wordpress.org/support/plugin/hafenstudios-ads/reviews/?filter=3)
 *  [  0 2-star reviews     ](https://wordpress.org/support/plugin/hafenstudios-ads/reviews/?filter=2)
 *  [  0 1-star reviews     ](https://wordpress.org/support/plugin/hafenstudios-ads/reviews/?filter=1)

[Your review](https://wordpress.org/support/plugin/hafenstudios-ads/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/hafenstudios-ads/reviews/)

## Penyumbang

 *   [ hafenstudios ](https://profiles.wordpress.org/hafenstudios/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/hafenstudios-ads/)