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, split testing, device and post-type targeting, campaign scheduling and consent gating are built in.
Sonar, cookieless analytics for the numbers Google Analytics never shows you. It counts the people who decline your cookie banner, detects AI crawler visits from GPTBot, ClaudeBot, PerplexityBot and 36 more, sorted by purpose and kept apart from classic search engines, lists the visits that AI assistants like ChatGPT and Perplexity send you, and runs a consent audit that tells you whether your own site fires tracking requests before visitors have decided. No cookies, no cloud, nothing leaves your server.
New in 2.7.0: Sonar is honest about its own numbers. It says since when it has been counting, compares page views with GA4 over exactly the same seven days, recognises ChatGPT visits that arrive without a referrer, and no longer counts headless browsers as people.
Highlights
- Sonar: cookieless visitor counting, AI crawler detection, AI referral tracking and a consent audit, all in your own database. See what GA4 does not.
- Split test two ad variants against each other: every variant with impressions, clicks and CTR, a data progress gauge, and a mark on the one that is ahead.
- Weighted ad rotation, cache-proof: blocks sharing a group name rotate in automatic placements and via
[adjet_ad_group name="header"]; the winner is picked in the visitor’s browser, so page caches cannot freeze the choice. - AdSense Wizard: Publisher-ID + Slot-ID are enough for responsive AdSense units, including in-article and multiplex formats.
- Nothing leaves your server: no external calls, no phoning home, statistics stay in your own database.
- Template gallery with 27 free templates: banners, native cards, testimonial, book/course card, seasonal deals, events, sponsor logo wall, notification bars, popups and a cookie consent banner with selectable cookie images.
- Automatic placements before content, after content, after paragraph N, in the middle of the content, before the last paragraph, after heading N or after the first image.
- Manual placement via shortcode
[adjet_ad id="1"], widget or Gutenberg block. - Clean, focused admin interface with brand bar, weekly summary and clear navigation tabs.
- 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_adjetwith an optional editor-access toggle. - Premium templates and features 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.jsfrompagead2.googlesyndication.comto 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). With a double opt-in template and redirect URL configured in the settings, the signup uses Brevo’s double opt-in endpoint (/contacts/doubleOptinConfirmation) and Brevo sends the confirmation mail; without them the contact is created directly and no confirmation mail is sent, which the form’s success message states honestly. 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








Blocks
This plugin provides 1 block.
- Hafenstudios Ads
Installation
- Upload the ZIP via Plugins > Add New > Upload Plugin.
- Activate the plugin.
- Open the new « Hafenstudios Ads » menu and create your first ad block.
- 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_adjetcapability 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_adjetcapability removed for good. -
Is there a REST API?
-
Yes. The
adjet/v1namespace exposes ad blocks (/blocks, CRUD), statistics (/stats) and settings (/settings). Authenticate with an Application Password; access requires themanage_adjetcapability.
Reviews
Contributors & Developers
“Hafenstudios Ads – Ad Manager, AdSense & Banner Ads” is open source software. The following people have contributed to this plugin.
Contributors“Hafenstudios Ads – Ad Manager, AdSense & Banner Ads” has been translated into 1 locale. Thank you to the translators for their contributions.
Translate “Hafenstudios Ads – Ad Manager, AdSense & Banner Ads” into your language.
Interested in development?
Browse the code, check out the SVN repository, or subscribe to the development log by RSS.
Changelog
2.7.2
- New: page caches are purged after you change an ad block. One minute after the last change, the plugin clears Super Page Cache, LiteSpeed Cache, Cache Enabler, WP Rocket, W3 Total Cache and WP Super Cache, whichever is installed, so new ads and split test variants reach cached pages without a manual purge. Several saves in a row purge once. The filter
adjet_purge_page_cache_on_saveswitches it off. - New: signups sent through a newsletter form are counted per ad block in the local statistics. Only the number is stored, never the address, and only while statistics are switched on. The Pro version can decide split tests by these signups instead of clicks.
- Changed: the upgrade page explains how Pro arrives (download link and licence by e-mail, the free version is switched off before Pro goes in) and shows the price plus VAT.
2.7.1
- Fixed: saving an ad in the template assistant no longer resets what the assistant does not show. A split test variant lost its group and weight there, so the test ended without a word, and « Serve only after cookie consent » and the targeting set in the expert editor were switched back as well. The assistant now only changes what it shows.
- Changed: « Open a copy in the HTML editor » and « Open a copy in the expert editor » in the assistant now take over the group, weight, targeting and « Serve only after cookie consent » of the original, as « Duplicate » does. The copy still starts paused.
- Fixed: the consent traffic light no longer says that all ads wait for the banner. With the banner, Auto Ads wait by default, a single ad block only when « Serve only after cookie consent » is ticked in it.
- Improved: the import from Advanced Ads now says when display or visitor conditions were left behind, one line per ad, as it already did for Ad Inserter rules.
- Fixed: uninstalling also removes the short-lived rate limit counters of tracking, blocker reports and newsletter signups. Like the click protection data, they go even when you keep everything else.
2.7.0
- Fixed: Sonar’s period buttons no longer pretend. « 30 days » added up only the days Sonar had actually been counting, without saying so, which made a two-week-old installation look like a month with a third less traffic than Google Analytics. The tab now says since when Sonar has been counting and how many days the figures really cover.
- Changed: the dark figure compares page views, not users. Google Analytics counts a returning visitor once for the whole period, Sonar once per day, so the old comparison put two different things side by side. Enter the views GA4 shows for the last seven days and Sonar compares exactly the same days: yesterday and the six before. Until Sonar has a full week of its own data, there is no factor. A user figure entered under 2.6 is not reused.
- Changed: the visitor tile is now called « Visitors per day, added up », because that is what it counts. The note below it explains the difference to GA4 in one sentence.
- New: visits from ChatGPT are recognised even when they arrive without a referrer. ChatGPT usually sends none but adds utm_source=chatgpt.com to its links, so Sonar missed most of these visits. It now reads that one parameter and keeps it only when it names a known AI assistant; any other campaign tag is ignored and never stored.
- Changed: AI crawlers are sorted by purpose. Fetched on behalf of a person means someone asked ChatGPT, Claude or Perplexity and the assistant opened your page to answer; then come the AI search indexes and AI training. Classic search engines (Bingbot, Applebot, PetalBot) are counted separately and no longer inflate the AI figure. On the site we compared, they had made up a third of it. Their fetches also no longer appear under « What AI crawlers read ».
- Changed: Amazonbot counts as training, not as a fetch on someone’s behalf. Google-Extended and Applebot-Extended left the detection list: they are robots.txt tokens and never appear in a user agent.
- New: headless browsers, testing tools and script clients (HeadlessChrome, Lighthouse, PageSpeed, Pingdom, Puppeteer, Playwright, Selenium, curl, python, and anything calling itself a bot, crawler or spider) are no longer counted as people.
- Changed: the consent audit says that it always covers the last seven days, whatever period is selected above it, and calls what it measures by its name: page views of visitors who have not decided yet.
- Changed: Sonar tidies up once a day on a schedule instead of waiting for the next visitor, so the 30-day limit and the daily salt also hold on quiet sites and behind full-page caches. Switching off local statistics now stops all of Sonar, including the server-side crawler count, and deletes the visitor hashes of the current day at once. The label of the setting says so.
- Fixed: the plugin’s own measurements no longer slow down your Largest Contentful Paint. Impressions and Sonar’s page view left the browser while the page was still being drawn, and Lighthouse adds every request that starts before the LCP moment to the LCP. On a site with the consent banner that cost about 0.4 seconds in PageSpeed Insights. Both now wait until three seconds after the page has loaded, or go out at once when the visitor leaves earlier. Clicks are still sent right away.
- Fixed: optimizers no longer delay the little script that hides the consent banner for visitors who already decided. With Autoptimize set to defer inline JavaScript, the banner flashed up again on every page view. The script now carries the same exclusions for Autoptimize, WP Rocket and Cloudflare Rocket Loader as the consent mode default.
- Fixed: when the consent banner appears, the keyboard focus lands on its first button as intended, not on the privacy link in the banner text, and the page no longer scrolls to the banner to give it focus.
- New: a warning in the dashboard when another consent plugin is active next to the built-in banner (Cookie Notice, Complianz, Borlabs Cookie, Real Cookie Banner, Cookiebot, CookieYes and a few more). Two banners cover each other on phones and store every decision twice.
- Fixed: in the newsletter popup and the exit-intent newsletter, the e-mail field no longer sticks out of the card on themes that change the box model of form fields. Field and button now line up in a column that does not depend on the theme’s CSS.
2.6.0
- New: Sonar, a tab of its own for the numbers Google Analytics never shows you. Three counters and one audit, all cookieless, all in your own database: the people who actually visited, the AI crawlers that read your pages, the visits AI assistants sent you, and an answer to the question whether your site tracks before visitors have decided.
- Sonar counts people with a script of under 2 KB that runs after the page has loaded, so pages served from a cache count too. Unique visitors come from a hash of address and browser with a salt that is thrown away at midnight, which means yesterday’s visitors can no longer be recognised, by us or by anyone else. The address itself is never written down, and visitors who block scripts are simply missing rather than estimated. The tab says so, next to every number.
- New: AI crawler detection, server-side, for 44 agents from OpenAI, Anthropic, Perplexity, Google, Microsoft, Meta, Apple, ByteDance, Amazon, Common Crawl, Mistral and others, grouped by vendor and by the pages they fetched. A visitor who is not a crawler causes no database work at all. Behind a page cache the server only sees the requests that miss the cache, and the tab says that too.
- New: AI referrals as a channel of their own. Visits arriving from ChatGPT, Perplexity, Claude, Copilot, Gemini and six more are counted per day and per landing page. In Google Analytics those sit somewhere between Pinterest and a forum link; here they have a name. No other referrer is stored.
- New: the consent audit. On first-time visitors who have not decided yet, Sonar checks whether a full analytics or pixel request went out before they clicked your banner, and names the host it went to. Red means a full hit, yellow means a cookieless consent mode ping, green means nothing was sent. On many sites this is the first honest answer to a question everyone assumes they already know.
- New: the dark figure. Enter the number of users Google Analytics reports for the last seven days and Sonar puts its own count next to it, with the factor between them. Below roughly 1,000 events per day Google models nothing, so everyone who declines or blocks is missing from that report without a trace. Without your input nothing is estimated.
- Changed: consent decisions are now counted in the free edition as well, including decisions made at a banner from another plugin via the WP Consent API or an IAB TCF banner. Only the evaluation, the acceptance rate with its trend and the A/B test of banners, stays with Pro, so upgrading later starts with a history instead of an empty chart.
- Fixed, and this one is on us: the link that asked for a review pointed at the review form with five stars already selected. The plugin directory considers that misleading, and rightly so. Both places now link to the plain review page, and the link text no longer shows stars.
- Changed: the book and course card no longer arrives with five stars filled in. A rating nobody gave does not belong in an ad; the field starts empty and offers one to five stars when you pick one.
- Uninstalling removes Sonar’s two tables along with everything else.
2.5.0
- Fixed: the templates now speak the language of your site. The close button, the consent banner’s screen-reader name and the e-mail placeholder were written into the markup in German, so a French site showed a German example address in its sign-up form despite seven bundled translations.
- New: overlays can be operated by keyboard. Escape closes a pop-up or exit overlay, the focus stays inside while it is open and returns where it came from afterwards. Both are announced as dialogs. The consent banner is deliberately exempt: a consent decision must not be dismissed by accident.
- New: click protection. The plugin caps how often one browser can click your ads: out of the box at most 3 clicks on the same block and 10 in total per visitor and 24 hours, both adjustable. Above the limit the click is either no longer counted or the block stays away from that visitor, your choice. The statistics show how many clicks the protection did not count, so it never looks like a counting bug.
- Nothing about your visitors is stored for this: no IP address, in clear text or otherwise, only a shortened and salted hash, for at most 24 hours, inside your own installation. Nothing is sent anywhere, no list of known bots is fetched from outside, and the decision falls while counting the click, so page caches never notice. Uninstalling takes this data with it either way.
- Fixed: two older statistics helpers hashed visitor addresses without a salt. They now use the same salted, shortened hash as everything else.
- The free edition no longer shows the internal working name anywhere in the interface.
- New: a « No automatic ads on this post » switch right in the editor, in the sidebar or as a meta box. It only removes the automatic placements: shortcode, widget and block stay, because someone placed those on purpose.
- New: with WooCommerce you can now target product pages and the shop page directly. Cart and checkout stay free of ads until you tick them yourself, even for blocks that otherwise run everywhere.
- New: two switches under « Advanced » for every ad with a link. « Mark as advertising » (rel= »sponsored nofollow ») is on by default, because that is Google’s requirement for paid links, and « Open in a new tab » always adds rel= »noopener ».
- New: a whole rotation group can now stand in when AdSense leaves a slot empty, not just a single ad. The browser picks the variant, exactly one is counted.
- New: per ad you can choose what happens when an ad blocker prevents it: quietly show another block instead of nothing. No plea to switch the ad blocker off, and the default stays « show nothing ».
- New: the ad list is sortable. Click Name, Status, Placement, Impressions, Clicks or CTR to order the table, click again to flip the direction. Impressions descending is always the starting point, and the choice is never remembered. Names with an umlaut or accent sort where you look for them.
- Stand-in ads follow the same rules as any other ad: scheduling, device selection and « logged-in users only » apply to them too, so an expired campaign no longer keeps running as a stand-in. A script inside a stand-in really runs after the swap.
- Improved: for placements inside the content the editor only offers the page types that actually apply there. No more checkboxes that do nothing.
- Improved: the diagnosis view (?adjet_debug=1) now also explains the new cases: the per-post switch, cart and checkout, and why no stand-in could be shown.
- Improved: consent banners stay out of the ad ranking, and the split test data gauge says « Data threshold reached » instead of « 442 of the 100 impressions it needs ».
- Note: existing ads keep their ad code unchanged, so the two link switches take effect once you save the ad. The assistant says so as soon as you open it.
- New: hold back third-party scripts such as tracking pixels until your visitors have given consent. You write every rule yourself, each one starts in trial mode and at first only logs what it would block, and you arm them one at a time. Scripts from your own domain and WordPress core scripts stay exempt, and an emergency brake releases everything again.
- New: a consent traffic light on the dashboard. It tells you when ads are running without a banner, or when a banner exists but Consent Mode v2 is missing, and a button next to it creates the banner from the template.
- New: consent sources. The plugin can exchange decisions with the WP Consent API and adopt the signals of an IAB TCF 2.x banner, so a banner you already run counts like the built-in one.
- New for advanced setups, off by default: « preload Google tags » (advanced consent mode). It only switches on together with an explicit confirmation and carries a plain note on §25 TDDDG. Only pure Google tags load early; every other script that requires consent keeps waiting.
- Consent banner: Decline is now just as prominent as Accept, same size and weight, only the colour differs. Banners you saved earlier are corrected as well.
- Consent banner: optional entrance animation (switched off automatically for reduced motion), four bundled cookie images and four text suggestions from snappy to elegant.
- The consent default-state script can no longer be pushed behind your tracking tags by optimisation plugins, and a new check reports it when another snippet still loads first.
- Without JavaScript the consent banner now disappears instead of standing there unusable.
- Overlays: the frequency setting (once per session, once per day) is part of the free version now.
- Blocks with a stored Pro trigger no longer fail silently: the block list and the editor say that the template default applies instead.
- The short date in the statistics follows your site language now; it always used the German format before.
Older entries (2.4.1 and earlier) live in changelog.txt inside the plugin folder.
