Add your own code to the plugin through its hooks

TermsFeed AutoTerms fires 5 actions and applies 6 legacy filters of its own that your WordPress theme or plugin hooks with add_action() and add_filter(). The plugin triggers 1 jQuery event as well, after the Update Notices render. Add every PHP callback in a plugin or in the theme functions.php, which WordPress loads before init.

Pass the number of arguments to add_action() or add_filter() for a hook with more than 1, such as 2 for wpautoterms_container. Each hook below fires at the moment its row names.

Hook Kind Arguments Fires
wpautoterms_container Action $where, $type While the plugin builds each of the 4 kit containers on a website page
wpautoterms_registered_cpt Action None On init, right after the post type wpautoterms_page registers
wpautoterms_dismissed_admin_notice Action $class, $id, $removed On each wpautoterms_notices_action request that carries c and id
wpautoterms_pre_editor Action $option Before each rich-text message editor on a kit screen
wpautoterms_post_editor Action $option After each rich-text message editor on a kit screen
atospp_tos_before_heading, atospp_tos_after_heading, atospp_tos_after_end Filter $html (an empty string) Around the Terms of Service of the legacy shortcodes
atospp_pp_before_heading, atospp_pp_after_heading, atospp_pp_after_end Filter $html (an empty string) Around the Privacy Policy of the legacy shortcodes
the_content Core filter $content On the content of a legal page that [wpautoterms page="..."] embeds
widget_title Core filter $title, $instance, $id_base On the title of the Legal Pages widget
post-load jQuery event None On document.body, after the Update Notices render

The plugin does not add a filter of its own to the legal page text, the kit settings, or what the Cookie Consent kit prints. Change those through the settings screens, Additional CSS, the plugin actions, and the core filters the_content and widget_title.

The wpautoterms_container action lets you echo markup into the 4 containers that hold the Cookie Notice, the Update Notices, and what the Cookie Consent kit prints. It passes $where, which is top or bottom, and $type, which is static or fixed. The plugin wraps what your callbacks echo in <div id="wpautoterms-<where>-<type>-container"> and does not print a wrapper for a container that stays empty.

The action fires on every page of your WordPress website, whether or not a kit is on. wp-login.php and wp-register.php do not get a container. The action fires for each container at its own point of the request.

  • Top static and top fixed, normal mode. The plugin builds them on the wp action at priority 20 and inserts them right after the <body> tag.
  • Top static and top fixed, compatibility mode. "Caching plugins compatibility mode" moves them to the footer, on wp_footer at priority 100002.
  • Bottom fixed and bottom static. Both print in the footer on wp_footer at priority 100002, bottom fixed first.
  • Kit output inside each container. The kits listen at priority 10, in the order Update Notices, Cookie Notice, then the Cookie Consent kit. A callback at priority 5 prints before the kit output, and a callback at priority 20 prints after it.

The main query is ready on wp, so conditional tags such as is_front_page() and is_singular() work inside the callback. The example prints a shipping message in the bottom fixed container of the front page, after any kit output.

add_action( 'wpautoterms_container', 'mytheme_autoterms_shipping_bar', 20, 2 );

/**
 * Prints a message in the bottom fixed container of TermsFeed AutoTerms on the front page.
 *
 * @param string $where top or bottom.
 * @param string $type  static or fixed.
 */
function mytheme_autoterms_shipping_bar( $where, $type ) {
	if ( 'bottom' !== $where || 'fixed' !== $type || ! is_front_page() ) {
		return;
	}

	echo '<div class="mytheme-shipping-bar">' . esc_html__( 'Free shipping on orders over $50.', 'mytheme' ) . '</div>';
}

On the front page, the <div id="wpautoterms-bottom-fixed-container"> element then holds the mytheme-shipping-bar element, after any kit output.

The notices script places the fixed containers above other elements and moves the body:before and body:after pseudo-elements by their height, but the bars still cover the content beneath them. The notices script loads only while the Cookie Notice or Update Notices kit is on. Look up the container ID of each position and the selectors of each bar in TermsFeed AutoTerms CSS Classes and Containers.

A page cache stores the bottom containers with the page, and the top containers under WP Super Cache, Cache Enabler, or compatibility mode. Some other page caches store the page without the top containers. Clear the cache after you change a callback, because a cached page keeps its stored copy of those containers. Set up page caching for the kits with WordPress Caching Plugins.

Run code after the post type registers with wpautoterms_registered_cpt

The wpautoterms_registered_cpt action fires on init at priority -999998, right after the plugin registers the post type wpautoterms_page. It does not pass any argument. Use it to add post type support or attach a taxonomy before any other init callback reads the post type.

The example adds thumbnail support to the post type. The Featured image box appears only in a theme that declares post-thumbnails support.

add_action(
	'wpautoterms_registered_cpt',
	function () {
		add_post_type_support( 'wpautoterms_page', 'thumbnail' );
	}
);

With that support, the legal page editor shows the Featured image box in its sidebar. Find the other properties of the post type in Query Legal Pages in WordPress Themes.

React to a dismissed admin notice with wpautoterms_dismissed_admin_notice

The wpautoterms_dismissed_admin_notice action fires on each request to the AJAX action wpautoterms_notices_action that carries the c and id parameters. It passes $class, the notice class (error, updated, or notice-info), $id, the notice id, and $removed, which is true when a stored notice was removed. Only a user with edit_wpautoterms_pages reaches it, with a valid nonce.

Version 3.0.8 of the plugin does not store a persistent admin notice of its own: the review request and the settings reminder save their dismissal through other requests. No plugin screen sends a wpautoterms_notices_action request, so the action fires only for requests that other code sends, with $removed false when no stored notice matched. The example logs only the dismissals that removed a stored notice.

add_action(
	'wpautoterms_dismissed_admin_notice',
	function ( $class, $id, $removed ) {
		if ( ! $removed ) {
			return;
		}

		error_log(
			sprintf(
				'TermsFeed AutoTerms notice "%s" (%s) dismissed by user %d',
				$id,
				$class,
				get_current_user_id()
			)
		);
	},
	10,
	3
);

Add content around the rich-text message editors with wpautoterms_pre_editor and wpautoterms_post_editor

The wpautoterms_pre_editor and wpautoterms_post_editor actions fire before and after each rich-text message editor on the Cookie Notice, Update Notices, and Endorsements screens. Both pass $option, the message field, whose name() method returns the editor ID, and both fire in the admin only.

Editor ID Field
wpautoterms_cookies_notice_message "Message" on the Cookie Notice screen
wpautoterms_update_notice_message "Message" on the Update Notices of Legal Pages screen
wpautoterms_update_notice_message_multiple "Message for multiple updated pages" on the Update Notices of Legal Pages screen
wpautoterms_endorsements_message "Disclaimer message" on the Endorsements screen

The plugin prints the "Insert shortcode:" links and the revert link from wpautoterms_post_editor at priority 10. Hook at priority 20 to print after those links, as the example does under the Cookie Notice message.

add_action(
	'wpautoterms_post_editor',
	function ( $option ) {
		if ( 'wpautoterms_cookies_notice_message' !== $option->name() ) {
			return;
		}

		echo '<p class="description">' . esc_html__( 'Keep the message to 2 sentences and link the Cookies Policy.', 'mytheme' ) . '</p>';
	},
	20
);

The note prints below the shortcode links of the "Message" field on the Cookie Notice screen.

Change the legacy shortcode output with the atospp filters

6 filters add HTML before and after the heading, and after the end, of each document that the legacy Auto Terms of Service and Privacy Policy 1.x shortcodes print. Each filter receives an empty string, and the plugin prints the value your callback returns without escaping it. Escape every value you add, as the example does.

Filter Where the returned HTML prints Shortcodes that print it
atospp_tos_before_heading Before the Terms of Service heading, h2#atospp-terms [my_terms_of_service], [my_terms_of_service_and_privacy_policy]
atospp_tos_after_heading After the Terms of Service heading [my_terms_of_service], [my_terms_of_service_and_privacy_policy]
atospp_tos_after_end After the end of the Terms of Service, its closing numbered list [my_terms_of_service], [my_terms_of_service_and_privacy_policy]
atospp_pp_before_heading Before the Privacy Policy heading, h2#atospp-privacy [my_privacy_policy], [my_terms_of_service_and_privacy_policy]
atospp_pp_after_heading After the Privacy Policy heading [my_privacy_policy], [my_terms_of_service_and_privacy_policy]
atospp_pp_after_end After the last paragraph of the Privacy Policy [my_privacy_policy], [my_terms_of_service_and_privacy_policy]

The filters run only while the legacy text shows. The legacy text needs "On / Displaying" in the On/Off field of the Legacy Auto TOS & PP screen and every required field filled. Without both conditions, the shortcodes print their "coming soon" text.

add_filter(
	'atospp_pp_after_heading',
	function ( $html ) {
		return $html . '<p class="mytheme-legacy-note">' . esc_html__( 'This policy applies to example.com and its subdomains.', 'mytheme' ) . '</p>';
	}
);

add_filter(
	'atospp_tos_after_end',
	function ( $html ) {
		return $html . '<p><a href="' . esc_url( home_url( '/contact/' ) ) . '">' . esc_html__( 'Contact us about these terms', 'mytheme' ) . '</a></p>';
	}
);

On a page with [my_terms_of_service_and_privacy_policy], the note follows the Privacy Policy heading and the contact link closes the Terms of Service. Find the legacy shortcodes and their settings in Legal Page Shortcodes for WordPress.

Core filters the plugin applies

The plugin applies 2 core WordPress filters, the_content and widget_title, so callbacks you already hook to them run on its output. Both pass the core arguments, so hook them with the code you already use for core output.

The [wpautoterms page="<slug>"] shortcode runs the content of the embedded legal page through the_content, so your the_content callbacks run on that content. The filter runs while WordPress expands the shortcodes of the host post. Your callbacks therefore run twice on a post that embeds a legal page: once for the embedded legal page, and once for the host post. The plugin runs the filter once per embedded page, and an escaped shortcode such as [[wpautoterms page_title]] in it stays text.

During the pass for the embedded page, get_post() still returns the host post, and the global $wpautoterms_post holds the embedded legal page. The example adds a share line to post content and leaves embedded legal pages untouched.

add_filter(
	'the_content',
	function ( $content ) {
		global $wpautoterms_post;

		if ( ! empty( $wpautoterms_post ) && 'wpautoterms_page' === get_post_type( $wpautoterms_post ) ) {
			return $content;
		}

		if ( ! is_singular( 'post' ) || ! in_the_loop() ) {
			return $content;
		}

		return $content . '<p class="mytheme-share">' . esc_html__( 'Share this post', 'mytheme' ) . '</p>';
	}
);

On a post that holds [wpautoterms page="privacy-policy"], the mytheme-share paragraph appears once in the page source, after the post content.

The Legal Pages widget passes its title through widget_title, with the widget settings as $instance and the id base wpautoterms_widget. The title arrives HTML-escaped, and the widget prints the value your callback returns as it is, as the core Pages widget does. An empty saved title arrives as "TermsFeed AutoTerms Plugin Legal Pages".

The example replaces that default title, and leaves a title someone typed in the widget as it is.

add_filter(
	'widget_title',
	function ( $title, $instance = array(), $id_base = '' ) {
		if ( 'wpautoterms_widget' !== $id_base || ! empty( $instance['title'] ) ) {
			return $title;
		}

		return esc_html__( 'Legal', 'mytheme' );
	},
	10,
	3
);

With the Title field of the widget left empty, the widget heading reads "Legal" on every page that shows the widget.

Run code after the Update Notices render with the post-load event

The plugin triggers the jQuery event post-load on document.body each time it renders the Update Notices, including a render with no notice. The event fires once for each render: from the notice data the page carries, or after the update check that the plugin sends from a cached page. Other scripts, such as infinite scroll, trigger post-load too, so check for the notice markup in your handler.

This script gives each notice the ARIA role status. Attach the handler at load time, in a script that loads in the footer, so it exists before the notices render.

jQuery( document.body ).on( 'post-load', function () {
	var notices = document.querySelectorAll( '#wpautoterms-update-notice-placeholder .wpautoterms-update-notice' );

	for ( var i = 0; i < notices.length; i++ ) {
		notices[ i ].setAttribute( 'role', 'status' );
	}
} );

The PHP enqueues the script from js/update-notice.js in a child theme, in the footer, with a dependency on jquery.

add_action(
	'wp_enqueue_scripts',
	function () {
		wp_enqueue_script(
			'mytheme-update-notice',
			get_stylesheet_directory_uri() . '/js/update-notice.js',
			array( 'jquery' ),
			'1.0.0',
			true
		);
	}
);

Each .wpautoterms-update-notice element then carries role="status" while the Update Notices bar shows. Find the other globals of the notices script in TermsFeed AutoTerms Script and Style Handles.