Having fun with AI, I (co-)created a Gutenberg block for adding Google AdSense ads in posts. Vibe coding your WordPress plugins, if AI keeps evolving like this I think a lot of WordPress agencies can close up shop. This block plugin allows me to add and place an advertisement where I want it within the content.
Do you see the Google AdSense ad above this paragraph? It is inserted automatically right after the <!--more--> tag or read more block, which this GeneratePress theme translates to <span id="more-nnnn"></span>. Where nnnn is the post ID of this post. I’m sure you have something against Google AdSense, but I think this is nice 🙂 .
Why creating a Gutenberg block for adding ads?
Over a decade I ago I wrote about a method of inserting Google ads into posts using WordPress shortcodes. Nowadays, this still works using the shortcode block, but I wanted something similar for Gutenberg as a regular block. Just because I can. If you want to read that old post, it’s in Dutch on ITFAQ.nl: Google AdSense advertenties in WordPress met shortcodes.
This WordPress Plugin for Google AdSense allows you to automatically add an advertisement after the “read more” block / tag, and it enables you to place ads between content blocks where you want them to appear.
This is how it looks:
- Search and add the block in your post where you want it to appear

- Click the block to insert it

- Choose your ad size / layout

There is no configuration, I hardcoded all data-ad-slot IDs.
Plugin code
The WordPress plugin for Google AdSense block support is only two files. Use the code to create something of your own. I’ve stripped the code from my Publisher ID and ad slot IDs, the rest of the code is AS-IS.
The two files are:
saotn-adsense-block.phpblock.js
saotn-adsense-block.php:
<?php
/**
* Gutenberg block for Adsense (no config)
*
* @wordpress-plugin
* Plugin Name: Gutenberg AdSense block after more tag/block
* Plugin URI: https://www.saotn.org
* Donate Link: https://www.paypal.me/jreilink
* Description: Gutenberg block places a Google AdSense ad in your WordPress content immediately after the more tag/block. If the more tag/block is absent, you can add the Google AdSense block anywhere in your content.
* Version: 1.0.11
* Author: Jan Reilink
* Author URI: https://www.saotn.org
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
function saotn_adsense_plugin_row_meta( $links, $file ) {
if ( ! preg_match( '/saotn-adsense-block.php$/', $file ) ) {
return $links;
}
// First link: Donate
$links[] = sprintf(
'<a href="https://www.paypal.me/jreilink" target="_blank" rel="noopener">%s</a>',
__( 'Donate' )
);
// Second link: website
$links[] = sprintf(
'<a href="https://www.saotn.org" target="_blank" rel="noopener">%s</a>',
__( 'Sysadmins of the North' )
);
return $links;
}
add_filter( 'plugin_row_meta', 'saotn_adsense_plugin_row_meta', 10, 2 );
function saotn_enqueue_adsense_scripts() {
// Use a static variable to keep track of
// whether the scripts have already been printed.
static $adsense_scripts_printed = false;
// If they have already been printed, break off immediately.
if ( $adsense_scripts_printed ) {
return;
}
// Perform the check for AMP or non-AMP
if ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) {
echo '<script async custom-element="amp-ad" src="https://cdn.ampproject.org/v0/amp-ad-0.1.js"></script>' . "\n";
} else {
echo '<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4625631977770447" crossorigin="anonymous"></script>' . "\n";
}
// Set the flag to true so that the next call is skipped.
$adsense_scripts_printed = true;
}
add_action( 'wp_head', 'saotn_enqueue_adsense_scripts', 10 );
/**
* 2. Gutenberg Block Dynamic Rendering
*/
function saotn_render_adsense_block_callback( $attributes, $content ) {
$format = isset( $attributes['format'] ) ? $attributes['format'] : 'horizontal';
switch ( $format ) {
case 'square':
$slot_id = 'ID_1';
break;
case 'vertical':
$slot_id = 'ID_2';
break;
case 'general':
$slot_id = 'ID_3';
break;
case 'horizontal':
default:
$slot_id = 'ID_4';
break;
}
ob_start();
?>
<div class="wp-block-saotn-adsense-block cta" data-format="<?php echo esc_attr( $format ); ?>">
<?php if ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) : ?>
<amp-ad width="100vw" height="320"
type="adsense"
data-ad-client="ca-pub YOUR Publisher ID"
data-ad-slot="<?php echo esc_attr( $slot_id ); ?>"
data-auto-format="rspv"
data-full-width="">
<div overflow="click to resize"></div>
</amp-ad>
<?php else : ?>
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub YOUR Publisher ID"
data-ad-slot="<?php echo esc_attr( $slot_id ); ?>"
data-ad-format="auto"
data-full-width-responsive="true"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<?php endif; ?>
</div>
<?php
return ob_get_clean();
}
/**
* 3. Gutenberg Block Registration
*/
function saotn_register_adsense_block_modern() {
wp_register_script(
'saotn-adsense-block-editor',
plugin_dir_url( __FILE__ ) . 'block.js',
array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components' ),
'1.0.11' // Versie verhoogd om cache te breken
);
// Shared arguments
$block_args = array(
'api_version' => 2,
'title' => 'SAOTN AdSense Block',
'category' => 'widgets',
'icon' => 'google',
'description' => 'Adds a Google AdSense advertisement (AMP-friendly).',
'editor_script' => 'saotn-adsense-block-editor',
'render_callback' => 'saotn_render_adsense_block_callback',
'attributes' => array(
'format' => array(
'type' => 'string',
'default' => 'horizontal',
),
),
);
// Register namespace
register_block_type( 'saotn/adsense-block', $block_args );
}
add_action( 'init', 'saotn_register_adsense_block_modern' );
/**
* 4. Automatic Injection Post More Tag / Block
*/
function saotn_inject_adsense_after_more( $content ) {
if ( ! is_singular( 'post' ) ) {
return $content;
}
// Do not inject automatic ad if either block is manually present
// if ( has_block( 'saotn/adsense-block', $content ) ) {
// return $content;
// }
$adsense_html = saotn_render_adsense_block_callback( array(), '' );
$adsense_block = "\n\n" . $adsense_html . "\n";
if ( preg_match( '/<span id="more-\d+"><\/span>/', $content ) ) {
$content = preg_replace( '/(<span id="more-\d+"><\/span>)/', '$1' . $adsense_block, $content, 1 );
}
elseif ( preg_match( '/.*?/s', $content ) ) {
$content = preg_replace( '/(.*?)/s', '$1' . $adsense_block, $content, 1 );
}
return $content;
}
add_filter( 'the_content', 'saotn_inject_adsense_after_more', 20 );
block.js:
( function( blocks, element, blockEditor, components ) {
var el = element.createElement;
var Fragment = element.Fragment;
var InspectorControls = blockEditor.InspectorControls;
var useBlockProps = blockEditor.useBlockProps;
var SelectControl = components.SelectControl;
var PanelBody = components.PanelBody;
var blockConfig = {
title: 'SAOTN AdSense Block',
icon: 'google',
category: 'widgets',
description: 'Adds a Google AdSense advertisement (AMP-friendly).',
attributes: {
format: {
type: 'string',
default: 'horizontal',
}
},
edit: function( props ) {
var format = props.attributes.format;
// Retrieve the official Gutenberg block properties (including drag/drop hooks)
var blockProps = useBlockProps( {
style: {
border: '1px dashed #ccc',
padding: '20px',
textAlign: 'center',
background: '#f9f9f9',
color: '#333',
marginBottom: '20px'
}
} );
function onChangeFormat( newFormat ) {
props.setAttributes( { format: newFormat } );
}
return el( Fragment, {},
// The sidebar settings (are moved to the sidebar by Gutenberg)
el( InspectorControls, { key: 'setting' },
el( PanelBody, { title: 'AdSense Settings', initialOpen: true },
el( SelectControl, {
label: 'Ad Format',
value: format,
options: [
{ label: 'Horizontal', value: 'horizontal' },
{ label: 'Square', value: 'square' },
{ label: 'Vertical', value: 'vertical' },
{ label: 'General (Legacy)', value: 'general' }
],
onChange: onChangeFormat,
__nextHasNoMarginBottom: true
} )
)
),
// The actual block wrapper in the editor content (fully selectable and movable)
el( 'div', blockProps, 'SAOTN AdSense Ad - Format: ' + format.toUpperCase() )
);
},
save: function() {
return null; // Server-side rendering via PHP callback
},
};
// Register the block namespace
blocks.registerBlockType( 'saotn/adsense-block', blockConfig );
} )( window.wp.blocks, window.wp.element, window.wp.blockEditor, window.wp.components );
Save both files in a directory saotn-adsense-block and upload to your wp-content/plugins folder. After activation there should be a Gutenberg block.
I’m not offering this as a download of publishing it to WordPress Plugin Directory. Use it as inspiration and create your own plugin functionality. Cheers! 🙂
Update: I also vibe coded a plugin to add a datetime in ISO format for the <ins> HTML tag (e.g 2026-06-26T08:53:56Z), when selecting text. See the HTML code for the word “Update” in this paragraph. This was inspired by the Abbreviation Button for the Block Editor plugin by Jb Audras. Both are great for accessibility and UX (user experience), IMO.
