One problem is that you’re hooking in too early. Reference the Hooks API Action Reference. Template conditionals such as is_page()
are only available after the query has been set up and parsed. The earliest action that you can usually safely rely on query conditionals is pre_get_posts
. You’re hooking into init
, which fires much earlier:
muplugins_loaded
After must-use plugins are loadedregistered_taxonomy
For category, post_tag, etc.registered_post_type
For post, page, etc.plugins_loaded
After active plugins and pluggable functions are loadedsanitize_comment_cookies
setup_theme
load_textdomain
For the default domainafter_setup_theme
Generally used to initialize theme settings/options.auth_cookie_malformed
auth_cookie_valid
set_current_user
init
Typically used by plugins to initialize. The current user is already authenticated by this time.widgets_init
Used to register sidebars. This is fired at ‘init’, with a priority of 1.register_sidebar
For each sidebar and footer areawp_register_sidebar_widget
For each widgetwp_default_scripts
(ref array)wp_default_styles
(ref array)admin_bar_init
add_admin_bar_menus
wp_loaded
After WordPress is fully loadedparse_request
Allows manipulation of HTTP request handling (ref array)send_headers
Allows customization of HTTP headers (ref array)parse_query
(ref array)pre_get_posts
Exposes the query-variables object before a query is executed. (ref array)posts_selection
wp
After WP object is set up (ref array)template_redirect
get_header
wp_enqueue_scripts
Given the nature of what you’re trying to do, I would recommend hooking into template_redirect
.