My Account Endpoint Generator
A new tab in the customer's My Account area — the endpoint, the menu entry, the content, and the once-only rewrite-rule flush wired to activation so the tab doesn't 404 on first load.
The tab
/my-account/loyalty-points/
Content
<?php // Generated with WP CodeKit — powered by GrowQuest (https://growquest.io). /** * Plugin Name: Loyalty Points account tab * Description: Adds the loyalty-points endpoint to My Account. * Version: 1.0.0 * Requires PHP: 7.4 * Requires Plugins: woocommerce * Text Domain: acme */ defined( 'ABSPATH' ) || exit; /** * Register the /my-account/loyalty-points endpoint. */ function acme_add_endpoint() { add_rewrite_endpoint( 'loyalty-points', EP_ROOT | EP_PAGES ); } add_action( 'init', 'acme_add_endpoint' ); /** * Tell WooCommerce's own query-var map about it. * * @param array $vars Existing query vars. * @return array */ function acme_query_vars( $vars ) { $vars['loyalty-points'] = 'loyalty-points'; return $vars; } add_filter( 'woocommerce_get_query_vars', 'acme_query_vars' ); /** * Add it to the My Account menu. * * @param array $items Existing items, keyed by endpoint slug, in display order. * @return array */ function acme_menu_item( $items ) { $new_items = array(); foreach ( $items as $key => $label ) { $new_items[ $key ] = $label; if ( 'orders' === $key ) { $new_items['loyalty-points'] = __( 'Loyalty Points', 'acme' ); } } return $new_items; } add_filter( 'woocommerce_account_menu_items', 'acme_menu_item' ); /** * Render the endpoint content. */ function acme_endpoint_content() { echo wp_kses_post( wpautop( __( 'You have earned 0 points so far. Points are added automatically when an order is marked complete.', 'acme' ) ) ); } add_action( 'woocommerce_account_loyalty-points_endpoint', 'acme_endpoint_content' ); /** * Flag a rewrite-rule flush for the next full page load — endpoints * registered on init are not live until the rules are rebuilt once. */ function acme_flag_flush() { update_option( 'acme_flush_rules', 1 ); } register_activation_hook( __FILE__, 'acme_flag_flush' ); /** * Flush once, after the endpoint above has actually been registered. */ function acme_maybe_flush() { if ( ! get_option( 'acme_flush_rules' ) ) { return; } delete_option( 'acme_flush_rules' ); flush_rewrite_rules(); } add_action( 'wp_loaded', 'acme_maybe_flush' ); register_deactivation_hook( __FILE__, 'flush_rewrite_rules' );