Skip to content

Instantly share code, notes, and snippets.

@jdevalk
Last active January 21, 2025 12:11
Show Gist options
  • Save jdevalk/4cf20e5816be56af171b5a71b9ba48bf to your computer and use it in GitHub Desktop.
Save jdevalk/4cf20e5816be56af171b5a71b9ba48bf to your computer and use it in GitHub Desktop.
The Events Calendar SEO fix

The Events Calendar SEO fix

This plugin fixes the horrible SEO mess that The Events Calendar can create.

The Events Calendar has been an SEO problem for ages, and I've reported these issues to them numerous times over the years. They have made some fixes, but it's still not enough and especially on a site that has been running TEC for a long time, the fixes are not good enough, as the problems are hidden, but not fixed.

Problems:

  • If you disable "day" or "month" views in the settings (on by default), those don't get linked, but they still work...
  • If you enable the month view cache (on by default), months without events are only noindex-ed on the first view of that page, when they're cached they no longer get noindex-ed. This plugin solves that by disabling this cache.
  • When TEC adds noindex to a page it does that by adding its own noindex tag, when it should just filter the wp_robots filter to add it, as that's what SEO plugins hook into too. Otherwise you will get two robots elements, with conflicting values.

Things that have been fixed but not good enough:

  • The Events Calendar no longer links to day or month views before your first event or after your last event, but, if those URLs get linked to elsewhere, they do still render with a 200 status code. So, if those are in Google's or another search engine's index, they will remain there... This plugin makes those URLs return a 404.
=== SEO Fix for The Events Calendar ===
Contributors: joostdevalk
Tags: the events calendar
Requires at least: 6.2
Tested up to: 6.7
Stable tag: 1.0
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
== Description ==
This plugin fixes the horrible SEO mess that The Events Calendar can create.
The Events Calendar has been an SEO problem for ages, and I've reported these issues to them numerous times over the years. They have made some fixes, but it's still not enough and especially on a site that has been running TEC for a long time, the fixes are not good enough, as the problems are hidden, but not fixed.
Problems:
* If you disable "day" or "month" views in the settings (on by default), those don't get linked, but they still work...
* If you enable the month view cache (on by default), months without events are only `noindex`-ed on the *first* view of that page, when they're cached they no longer get `noindex`-ed. This plugin solves that by disabling this cache.
* When TEC adds `noindex` to a page it does that by adding its _own_ `noindex` tag, when it should just filter the `wp_robots` filter to add it, as that's what SEO plugins hook into too. Otherwise you will get _two_ `robots` elements, with conflicting values.
Things that have been fixed but not good enough:
* The Events Calendar no longer links to day or month views _before_ your first event or _after_ your last event, but, if those URLs get linked to elsewhere, they do still render with a `200` status code. So, if those are in Google's or another search engine's index, they will remain there... This plugin makes those URLs return a 404.
== Installation ==
1. Upload the `seo-fix-tec` folder to the `/wp-content/plugins/` directory.
2. Activate the plugin through the 'Plugins' menu in WordPress.
== Changelog ==
= 1.0 =
* Initial release.
<?php
/**
* Plugin Name: SEO Fix for The Events Calendar
* Plugin URI: https://github.com/jdevalk/seo-fix-tec
* Description: A plugin to fix and enhance The Events Calendar functionality
* Version: 1.0.0
* Author:
* Author URI: https://joost.blog/
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
// Disable caching as it breaks the noindex functionality.
add_filter( 'tribe_events_views_v2_should_cache_html', '__return_false' );
add_filter( 'tec_events_seo_robots_meta_include', function( $do_noindex ) {
// If the noindex is enabled, add the noindex to the WordPress core robots meta tag (which SEO plugins also use).
if ( $do_noindex ) {
// Add noindex to the WordPress robots meta tag.
add_filter( 'wp_robots', function( $robots ) {
$robots['noindex'] = true;
return $robots;
}, 10, 1 );
// Remove the Yoast SEO canonical URL from the page, as that potentially breaks the noindex functionality.
// Yoast should not be outputting a canonical URL in this case, but it seems to do so anyway.
add_filter( 'wpseo_canonical', '__return_false' );
// Return false to prevent the default behavior of adding a second robots meta tag.
return false;
}
return $do_noindex;
}, 999, 1 );
add_filter( 'send_headers', function() {
global $wp_query;
if ( isset( $wp_query->query['post_type'] ) && $wp_query->query['post_type'] === 'tribe_events' && isset( $wp_query->query['eventDisplay'] ) ) {
if ( $wp_query->query['eventDisplay'] === 'month' ) {
// If the month view is disabled, always return a 404.
$raw_options = Tribe__Settings_Manager::get_options();
if ( ! in_array( 'month', $raw_options['tribeEnableViews'] ) ) {
$wp_query->set_404();
return;
}
// If the month view is enabled, but the earliest event date is after the current month, return 404.
if ( tribe_events_earliest_date( 'Y-m' ) > $wp_query->query['eventDate'] ) {
$wp_query->set_404();
return;
}
// If the month view is enabled, but the latest event date is before the current month, return 404.
if ( tribe_events_latest_date( 'Y-m' ) < $wp_query->query['eventDate'] ) {
$wp_query->set_404();
return;
}
}
if ( $wp_query->query['eventDisplay'] === 'day' ) {
// If the day view is disabled, always return a 404.
$raw_options = Tribe__Settings_Manager::get_options();
if ( ! in_array( 'day', $raw_options['tribeEnableViews'] ) ) {
$wp_query->set_404();
return;
}
// If the day view is enabled, but the currently shown date is before the earliest event date, return 404.
if ( strtotime( tribe_events_earliest_date( 'Y-m-d' ) ) > strtotime( $wp_query->query['eventDate'] ) ) {
$wp_query->set_404();
return;
}
// If the day view is enabled, but the currently shown date is after the latest event date, return 404.
if ( strtotime( tribe_events_latest_date( 'Y-m-d' ) ) < strtotime( $wp_query->query['eventDate'] ) ) {
$wp_query->set_404();
return;
}
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment