GeneratorsWooCommerceMy Account Endpoint

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.

loyalty-points-account-endpoint.php
Saved just now
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' );