Page Arguments and Dynamic Pages
I believe you want to change your listings_menu()

function listings_menu() {
    $items = array();

    $items['site/listings/%'] = array(
        'title' =&gt; 'City Listings',
        'page callback' =&gt; 'business_listings',
        'access arguments' =&gt; array('access content'),
        'page arguments' =&gt; array(3),
    );

    return $items;
}


Then you need to change your listings to accept that argument

function business_listings($states){
  $states = listing_states($states);

  $dbquery = db_query("SELECT DISTINCT CityName FROM {zipcodes} WHERE StateName = '".ucfirst(arg(2))."' ORDER BY CityName ASC");

  $cityname = '';
  $cityname .= '&lt;div class="city-wrapper"&gt;';
  foreach ($dbquery as $dbrow) {
      $cityname .='&lt;div class="cityname" style="float:left; width:200px;"&gt;';
      $cityname .= '&lt;a href="'.arg(2).'/'.strtolower(urlencode($dbrow-&gt;CityName)).'"&gt;'.$dbrow-&gt;CityName.'&lt;/a&gt;';
      $cityname .= '&lt;/div&gt;';
  }
  $cityname .= '&lt;/div&gt;';

  return array('states' =&gt; $states, 'city_names' =&gt; $cityname);
}