diff --git a/ad.install b/ad.install
index d32d963..e4b4e99 100644
--- a/ad.install
+++ b/ad.install
@@ -47,13 +47,6 @@ function ad_schema() {
         'default' => '',
         'description' => 'Ad type',
       ),
-      'redirect' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Ad redirect URL',
-      ),
       'autoactivate' => array(
         'type' => 'int',
         'not null' => TRUE,
@@ -483,3 +476,12 @@ function ad_update_6008() {
   $ret[] = update_sql("UPDATE {blocks} SET cache = ". BLOCK_CACHE_PER_PAGE ." WHERE module = 'ad'");
   return $ret;
 }
+
+/** 
+ * Drop unnecessary 'redirect' column 
+ */
+function ad_update_6009() {
+  $ret = array();
+  db_drop_field($ret, 'ads', 'redirect');
+  return $ret;
+}
diff --git a/ad.module b/ad.module
index 0850a24..160cf35 100644
--- a/ad.module
+++ b/ad.module
@@ -75,6 +75,7 @@ function ad_theme() {
  */
 function ad($group = FALSE, $quantity = 1, $options = array()) {
   global $base_url;
+  global $base_path;
 
   $adserve = variable_get('adserve', '');
   $adserveinc = variable_get('adserveinc', '');
@@ -84,6 +85,13 @@ function ad($group = FALSE, $quantity = 1, $options = array()) {
     $adserve = variable_get('adserve', '');
     $adserveinc = variable_get('adserveinc', '');
   }
+
+  // Update the base path.  This could be cleared when caches are cleared.
+  // It's used by serve.php to get the proper site base path, instead of serve.php's base path.
+  $ad_base_path = variable_get('ad_base_path','');
+  if (empty($ad_base_path)) {
+     variable_set('ad_base_path', $base_path);
+  }
   if (!file_exists($adserve) || !file_exists($adserveinc)) {
     drupal_set_message(t('Ads cannot be displayed.  The ad module is <a href="@misconfigured">misconfigured</a>, failed to locate the required <em>serve.php</em> ond/or <em>adserve.inc</em> file.', array('@misconfigured' => url('admin/content/ad/configure'))), 'error');
     _ad_check_installation();
@@ -232,7 +240,7 @@ function ad_redirect($aid, $group = NULL) {
     $status = 0;
   }
   // Allow source url to be passed in.
-  $url = isset($_GET['u']) ? $_GET['u'] : '';
+  $url = isset($_GET['url']) ? $_GET['url'] : '';
   if (!isset($url) || !valid_url($url)) {
     $url = referer_uri();
   }
@@ -261,6 +269,43 @@ function ad_redirect($aid, $group = NULL) {
 }
 
 /**
+ * AD API Helper
+ * ad_l() : like l(), but for ads.  This function uses the site's
+ * base path even when the request goes to sites/all/modules/ad/serve.php
+ * which would otherwise add 'sites/all/modules/ad' to the $base_path;
+ * 
+ */
+function ad_l($text, $ad, $options){
+  return l($text, ad_link_url($ad), $options);
+}
+
+/**
+ * AD API Helper
+ * ad_link_url(): Create the full URL for a redirect based on the ad node.
+ */
+function ad_link_url($node) {
+  global $base_root;
+  $ad_base_path = variable_get('ad_base_path', '/');
+
+/*  _debug_echo("ad path components: >>$base_root<< >>$ad_base_path<<");
+  _debug_echo("ad_l Path: $path");  
+*/
+  return $base_root.$ad_base_path.ad_link_path($node);
+}
+
+/**
+ * Ad API Helper Function:
+ * Create the redirect path for this ad suitable for passing to url() or l().
+ */
+function ad_link_path($node) {
+  if (!is_object($node)) {
+    return "ad/redirect/0";
+    exit(0);
+  }
+  return 'ad/redirect/' . $node->aid . '/@HOSTID___';
+}
+
+/**
  * Ad API Helper Function:
  * Append all necessary attributes to <a> tags.
  */
@@ -306,6 +351,13 @@ function ad_rebuild_cache($verbose = FALSE) {
 }
 
 /**
+ * Implementation of hook_flush_caches()
+ */
+function ad_flush_caches() {
+  variable_del('ad_base_path');
+}
+
+/**
  * Ad API Helper Function:
  * Append rel="nofollow" if globally enabled.
  */
@@ -942,7 +994,7 @@ function ad_nodeapi(&$node, $op, $teaser, $page) {
         if (!isset($node->maxclicks)) {
           $node->maxclicks = 0;
         }
-        db_query("INSERT INTO {ads} (aid, uid, adstatus, adtype, redirect, autoactivate, autoexpire, activated, maxviews, maxclicks) VALUES(%d, %d, '%s', '%s', '%s', %d, %d, %d, %d, %d)", $node->nid, $node->uid, $node->adstatus, $node->adtype, url('ad/redirect/'. $node->nid, array('absolute' => TRUE)), $node->autoactivate, $node->autoexpire, $activated, $node->maxviews, $node->maxclicks);
+        db_query("INSERT INTO {ads} (aid, uid, adstatus, adtype, autoactivate, autoexpire, activated, maxviews, maxclicks) VALUES(%d, %d, '%s', '%s', '%s', %d, %d, %d, %d, %d)", $node->nid, $node->uid, $node->adstatus, $node->adtype, $node->autoactivate, $node->autoexpire, $activated, $node->maxviews, $node->maxclicks);
         ad_statistics_increment($node->nid, 'create');
       }
       break;
@@ -989,7 +1041,7 @@ function ad_nodeapi(&$node, $op, $teaser, $page) {
           ad_statistics_increment($node->nid, $node->adstatus);
         }
         // Update ads table with new information.
-        db_query("UPDATE {ads} SET uid = %d, adstatus = '%s', adtype = '%s', redirect = '%s', autoactivate = %d, autoexpire = %d, activated = %d, maxviews = %d, maxclicks = %d, expired = %d WHERE aid = %d", $node->uid, $node->adstatus, $node->adtype, url('ad/redirect/'. $node->nid, array('absolute' => TRUE)), $node->autoactivate, $node->autoexpire, isset($activated) ? $activated : 0, isset($node->maxviews) ? (int)$node->maxviews : 0, isset($node->maxclicks) ? (int)$node->maxclicks : 0, isset($expired) ? $expired : 0, $node->nid);
+        db_query("UPDATE {ads} SET uid = %d, adstatus = '%s', adtype = '%s', autoactivate = %d, autoexpire = %d, activated = %d, maxviews = %d, maxclicks = %d, expired = %d WHERE aid = %d", $node->uid, $node->adstatus, $node->adtype, $node->autoactivate, $node->autoexpire, isset($activated) ? $activated : 0, isset($node->maxviews) ? (int)$node->maxviews : 0, isset($node->maxclicks) ? (int)$node->maxclicks : 0, isset($expired) ? $expired : 0, $node->nid);
         ad_statistics_increment($node->nid, 'update');
       }
       break;
diff --git a/ad_token.inc b/ad_token.inc
index 6fe845a..446a2ed 100644
--- a/ad_token.inc
+++ b/ad_token.inc
@@ -26,7 +26,7 @@ function ad_token_values($type, $object = NULL, $options = array()) {
         $values['type'] = $node->adtype;
         $values['status'] = $node->adstatus;
         $values['url'] = url('node/'. $node->nid, array('absolute' => TRUE));
-        $values['redirect'] = url($node->redirect, array('absolute' => TRUE));
+        $values['redirect'] = url(ad_link_path($node), array('absolute' => TRUE));
         $values['comments'] = $node->comment_count;
 
         $values['created_small'] = format_date($node->created, 'small');
diff --git a/adcache.inc b/adcache.inc
index 7a707de..2cae435 100644
--- a/adcache.inc
+++ b/adcache.inc
@@ -464,7 +464,7 @@ function adserve_cache_display($ids) {
   $ads = 0;
   foreach ($ids as $id) {
     $ad = adserve_cache('display_ad', $id);
-    _debug_echo('ad: '. htmlentities($ad));
+    _debug_echo("($id) ad: ". htmlentities($ad));
     // if displaying multiple ads, separate each with a div
     if ($output) {
       $group = adserve_variable('group');
diff --git a/adserve.inc b/adserve.inc
index 45e927f..8059246 100644
--- a/adserve.inc
+++ b/adserve.inc
@@ -291,6 +291,7 @@ function adserve_bootstrap($bootstrap = NULL) {
   echo _debug_echo("Drupal bootstrap '$bootstrap'.");
 
   drupal_bootstrap($bootstrap);
+
   echo _debug_echo("Drupal bootstrap complete.");
 }
 
@@ -299,6 +300,10 @@ function adserve_bootstrap($bootstrap = NULL) {
  */
 function adserve_debug() {
   if (adserve_variable('debug')) {
+    global $base_url;
+    global $base_root;
+    echo "Base Root: $base_root<br/>";
+    echo "Base URL: $base_url<br/>";
     echo "Root drupal directory detected as '". adserve_variable('root_dir') ."'.<br />\n<br />\n";
 
     $ad_dir = adserve_variable('ad_dir');
diff --git a/documentation/INSTALL.txt b/documentation/INSTALL.txt
index 2d8f4d7..708a896 100644
--- a/documentation/INSTALL.txt
+++ b/documentation/INSTALL.txt
@@ -75,3 +75,10 @@ Installation:
     image uploads more organized, you may want to use one of the following modules
       http://drupal.org/project/filefield_paths
       http://drupal.org/project/uploadpath
+      
+13. Because the serve.php and site's normal index.php do not reside in the same
+    directory, the site's base path is cached in the database.  Serve.php will use
+    the saved base path when determining the location for some ad content, like 
+    images.  If you migrate a site with ads, you may need to flush all caches to 
+    force the ad module to update the base path before ads, especially image ads, 
+    will show again.
diff --git a/documentation/ad_types.txt b/documentation/ad_types.txt
index 1f9dae7..e9a22f5 100644
--- a/documentation/ad_types.txt
+++ b/documentation/ad_types.txt
@@ -1,9 +1,9 @@
 ---------
 Overview:
 ---------
-This document is intended to help someone write a module for the ad api to
+This document is intended to help someone write a module for the ad API to
 introduce a new ad type. The core ad module includes two ad type modules, one
-for text ads and another for image ads. You can use the same api used by these
+for text ads and another for image ads. You can use the same API used by these
 two ad type modules to create your own custom ad type module, for example you
 may wish to write a module to ad support for flash ads. Some familiarity with
 Drupal and PHP is required.
@@ -52,18 +52,18 @@ are not available to you as the adtype.php script will only bootstrap to
 DRUPAL_BOOTSTRAP_DATABASE.
 
 You are passed in an object which contains the ad ID (aid) and the redirect
-URL (ie 'ad/redirect/13'). Utilize this information to return the complete
+URL path (i.e. 'ad/redirect/13'). Utilize this information to return the complete
 advertisement. For example:
 
 function ad_static_display_ad($ad) {
-  $return "<a href=\"$ad->redirect\">Static ad #$ad->aid</a>";
+  $return l("Static ad $ad->aid", ad_link_path($ad));
 }
 
 --------------------------------
 Sharing your new ad_type module:
 --------------------------------
 The drupal.org CVS contributions repository requires that all included modules
-be licesensed under the GPL. The ad module is dual licensed under both the
+be licensed under the GPL. The ad module is dual licensed under both the
 GPL and the BSD license, meeting this requirement. You can license your
 new ad_style module under just the GPL, or under a dual license as long as
 one of the licenses is the GPL.
diff --git a/image/ad_image.module b/image/ad_image.module
index a695b9d..9bf6d79 100644
--- a/image/ad_image.module
+++ b/image/ad_image.module
@@ -26,12 +26,12 @@ function ad_image_display_ad($ad) {
 function theme_ad_image_ad($ad) {
   if (isset($ad->aid) && (isset($ad->filepath) || isset($ad->remote_image))) {
     $output = '<div class="image-advertisement" id="ad-'. $ad->aid .'">';
+    $image = theme('ad_image_image', !empty($ad->remote_image) ? $ad->remote_image : $ad->filepath, check_plain($ad->tooltip), check_plain($ad->tooltip));
     if (isset($ad->url) && !empty($ad->url)) {
-      $image = theme('ad_image_image', !empty($ad->remote_image) ? $ad->remote_image : $ad->filepath, check_plain($ad->tooltip), check_plain($ad->tooltip));
-      $output .= l($image, $ad->redirect .'/@HOSTID___', array('attributes' => ad_link_attributes(), 'absolute' => TRUE, 'html' => TRUE));
+      $output .= ad_l($image, $ad, array('attributes' => ad_link_attributes(), 'absolute' => TRUE, 'html' => TRUE));
     }
     else {
-      $output .= theme('ad_image_image', !empty($ad->remote_image) ? $ad->remote_image : $ad->filepath, check_plain($ad->tooltip), check_plain($ad->tooltip));
+      $output .= $image;
     }
     $output .= '</div>';
     return $output;
diff --git a/text/ad_text.module b/text/ad_text.module
index 9381da1..7cd1831 100644
--- a/text/ad_text.module
+++ b/text/ad_text.module
@@ -28,9 +28,14 @@ function theme_ad_text_ad($ad) {
     if (!isset($ad->adheader)) {
       $ad = node_load($ad->aid);
     }
+
+    $safe_adheader = ad_text_display_prepare($ad->body, $ad->format);
+    $safe_adbody = ad_text_display_prepare($ad->body, $ad->format);
+    $ad_link = $ad->url ? ad_link_url($ad) : NULL;
+
     $output = '<div class="text-advertisement" id="ad-'. $ad->aid .'">';
     if (isset($ad->url) && !empty($ad->url)) {
-      $output .= theme('ad_text_text', ad_text_display_prepare($ad->adheader, $ad->format), ad_text_display_prepare($ad->adbody, $ad->format), $ad->redirect .'/@HOSTID___');
+      $output .= theme('ad_text_text', ad_text_display_prepare($ad->adheader, $ad->format), ad_text_display_prepare($ad->adbody, $ad->format), $ad_link);
     }
     else {
       $output .= theme('ad_text_text', ad_text_display_prepare($ad->adheader, $ad->format), ad_text_display_prepare($ad->adbody, $ad->format));
