Hook: mam_specials_get_post_radius

Signature

apply_filters( 'mam_specials_get_post_radius', int $radius );
Parameter Type Description
$radius int Default search radius in miles. The plugin’s own caller passes 5.

Returns: int — the radius in miles. You must return it.


Purpose

Sets the search radius used by the nearby-offers feed to decide which published special offers are close enough to the requesting device to appear. The plugin’s mam_special_offers::get_data_for_app() walks every published offer, resolves each offer’s parent-listing coordinates, and computes a great-circle distance from $_REQUEST['lat'] / $_REQUEST['lon']. Offers within $radius miles are returned; the rest are dropped.

The default of 5 miles is tight on purpose — it’s tuned for hyperlocal apps where you only want offers in the same neighborhood as the user. Any app serving a wider area will need to bump it.

This filter has no admin-side equivalent. Unlike mam-geofilters, the special-offers radius is not stored in role settings or a per-app option — it is purely code-driven.


When it runs

Inside mam_special_offers::get_data_for_app() (includes/content-class-special-offers.php), once per request:

$radius = apply_filters( 'mam_specials_get_post_radius', 5 );
foreach ( $posts as $post ) {
    // ... resolve $lat / $lon for the offer's parent ...
    if ( MAM_Input_Validator::is_null_island( $req_lat, $req_lon )
        || $this->distance_between( $req_lat, $req_lon, $lat, $lon ) < $radius ) {
        $dir_details[] = $this->get_post_content( $post );
    }
}

Note the MAM_Input_Validator::is_null_island() short-circuit: when the request supplies no usable GPS ($req_lat / $req_lon at (0, 0)), the distance test is skipped and every offer is returned regardless of the radius. The radius only filters when the device sends real coordinates.

The filter fires once per request, before the per-offer loop. It is not consulted on the listing-detail offers section (which only checks the offer’s parent linkage). It only affects the location-aware offers list.


Default behavior

mam_specials_get_post_radius → 5  (miles)

Offers whose parent listing has no resolvable coordinates resolve to (0, 0). Against a device sending real GPS, those offers compute a large distance and are filtered out — increasing the radius does not make them visible by accident. Against a device sending no GPS ($req_lat / $req_lon at (0, 0)), the MAM_Input_Validator::is_null_island() guard short-circuits the distance check and all published offers are returned regardless of radius — see the gotchas below.


Examples

Wider radius for a regional app

add_filter( 'mam_specials_get_post_radius', static fn () => 50 );

A constant override is fine — there’s only one decision per request.

Per-role radius

add_filter( 'mam_specials_get_post_radius', 'my_app_specials_radius' );

function my_app_specials_radius( $radius ) {
    if ( current_user_can( 'premium_member' ) ) {
        return 100;
    }
    return $radius;
}

Tied to the geofilters radius

If the same app uses mam-geofilters, you may want the special-offers feed to respect the user’s chosen geofilter radius rather than its own:

add_filter( 'mam_specials_get_post_radius', 'my_app_match_geofilter_radius' );

function my_app_match_geofilter_radius( $radius ) {
    return (int) apply_filters( 'mam_geofilter_radius', $radius );
}

This delegates to the geofilters resolution chain ($_REQUEST['radius'] → per-role setting → default 25, capped at 3000). See the geofilters plugin’s own Hook: mam_geofilter_radius for the chain’s details.


Gotchas

  • Comparison is strict less-than. The check is distance < $radius, not <=. An offer exactly at the boundary will not appear. Returning 5.0 is functionally identical to returning 5.
  • $req_lat / $req_lon come from $_REQUEST via floatval(). A request with no GPS gets (0, 0). The loop guards this with MAM_Input_Validator::is_null_island( $req_lat, $req_lon ): when the request coordinates are null-island (0, 0), the distance check is short-circuited and every published offer is returned regardless of what this filter returns (a deliberate “show everything when we don’t know where you are” fallback). The radius only takes effect when the device sends real coordinates.
  • The 5-mile default is per request, not cached. Adding an expensive callback (DB lookup, remote call) here adds latency to every nearby-offers request. If you’re computing the radius from per-user data, cache it.

Verification

This article was last verified against:

  • Plugin: mam-special-offers v2.1
  • Source: mam-special-offers/includes/content-class-special-offers.php (get_data_for_app)

Re-verify whenever the default radius (5) changes, the comparison operator in get_data_for_app() changes, or the lat/lon source for the request changes from $_REQUEST['lat'] / $_REQUEST['lon'].


  • Plugin: mam-special-offers
  • Hook: mam_specials_get_post_lat — companion hook for overriding parent coordinates
  • Hook: mam_special_offers_deals_allowed
  • Hook: mam_special_offers_skip_tab_bar_button

Metadata

Field Value
Article type Hook Reference
Plugin slug mam-special-offers
Applies to plugin version 2.1+
Category Extending MAM Suite
Hook type filter
Audience PHP developer
Last verified 2026-05-01
Was this article helpful?
Contents

    Need Support?

    Can't find the answer you're looking for? Don't worry we're here to help!