Fixing the Interspire Google Base Feed

Google Base updates their guidelines faster than Interspire updates its Shopping Cart.

Google loves when we feed it products.Upon launching the new MakeUpMania.com website, I discovered that the XML feed that Interspire generates for Google Base is not properly structured. There were many hits and misses before making the modifications necessary to get the feed approved.

Fixing the generated feed

Below are fixes to three issues that kept throwing errors on the Google Base side.

On months with more than 30 days, it causes an error.

Google requires the <g:expiration_date> field to be fewer than 30 days in the future. Interspire’s PHP code generates a date one month in the future. Months can be longer than 30 days, thus a problem occurs.

The fix:
In /store-root/admin/includes/classes/class.froogle.php, around line 87, find:
$expirationDate = isc_date("Y-m-d", strtotime('+1 month'));

Replace with:
$expirationDate = isc_date("Y-m-d", strtotime('+29 days'));

Google only accepts unique products with descriptions.

Interspire’s Google Base feed creates duplicates of the same product. Also, it exports all products, not just products with descriptions. Google requires product descriptions, and will disapprove a feed because of this.

The fix:
In /store-root/admin/includes/classes/class.froogle.php, around line 72, find:

WHERE
	p.prodvisible=1

Add below it:

	AND p.proddesc != ''
	GROUP BY p.productid

This will only retrieve products with a description and will not show the same product twice.

That should do it.

Let me know if you are still encountering issues with your Interspire feed.

Related posts:

  1. How to Create a Custom RSS Feed in WordPress in 12 Lines of Code
  2. Preview Hidden Products in Interspire Shopping Cart
  3. Improve Interspire Shopping Cart Search with Smart Redirections

Interspire & BigCommerce WordPress Plugin

Integrate Interspire or BigCommerce with your WordPress website

You want to spend your time writing the best content, not hunting for the link for the product you’re blogging about. This plugin is simple to set up, and powerful. If you use WordPress and Interspire or BigCommerce, it’s a must have.

For for information, check out the plugin information & download page on WordPress.org

Planned future updates:

  • Insert a product image (with an option to choose which size)
  • Improve shortcode by shortening length
  • Import product information into custom fields
  • Import all products into WordPress (as an Import module, using custom Post Types)
  • Integrate registration with the Interspire or BigCommerce APIs (add a new user as a customer)
  • Leave a comment below for a requested feature!

Questions? Requests? Comments? Bugs?

Please leave your feedback below, and I’ll do my best to address any issues you have, and also to integrate any requests into the plugin.

Thanks, and enjoy!

Related posts:

  1. WordPress Content Spinner Plugin – SEO WordSpinner
  2. Mad Mimi Plugin for WordPress
  3. Incorporate WordPress with Interspire Shopping Cart

Preview Hidden Products in Interspire Shopping Cart

Preview Hidden Products in Interspire Shopping Cart

Interspire Shopping Cart admins need to preview products before they go live.

Yep, we’re talking about Interspire once again today. 

The Interspire Shopping Cart doesn’t allow you to preview products that you are editing without making the product live in the store. This is plain silly; it’s vital for store owners to make sure their products pages look just as they expect when they make the product live in their store. As it is currently (in Interspire 5.5.x), this is not possible.

All it takes is one minor change in code, and your world gets a lot easier.

Mod: Preview Products That are Not Visible

Find the following code in includes/classes/class.products.php near line 126:

$query = "
	SELECT p.*, FLOOR(prodratingtotal/prodnumratings) AS prodavgrating, pi.*, ".GetProdCustomerGroupPriceSQL().",
	(SELECT COUNT(fieldid) FROM [|PREFIX|]product_customfields WHERE fieldprodid=p.productid) AS numcustomfields,
	(SELECT COUNT(reviewid) FROM [|PREFIX|]reviews WHERE revstatus='1' AND revproductid=p.productid AND revstatus='1') AS numreviews,
	(SELECT brandname FROM [|PREFIX|]brands WHERE brandid=p.prodbrandid) AS prodbrandname,
	(SELECT COUNT(imageid) FROM [|PREFIX|]product_images WHERE imageprodid=p.productid) AS numimages,
	(SELECT COUNT(discountid) FROM [|PREFIX|]product_discounts WHERE discountprodid=p.productid) AS numbulkdiscounts
	FROM [|PREFIX|]products p
	LEFT JOIN [|PREFIX|]product_images pi ON (pi.imageisthumb=1 AND p.productid=pi.imageprodid)
	WHERE ".$productSQL." AND p.prodvisible='1'
";

Replace this code with:

$query = "
	SELECT p.*, FLOOR(prodratingtotal/prodnumratings) AS prodavgrating, pi.*, ".GetProdCustomerGroupPriceSQL().",
	(SELECT COUNT(fieldid) FROM [|PREFIX|]product_customfields WHERE fieldprodid=p.productid) AS numcustomfields,
	(SELECT COUNT(reviewid) FROM [|PREFIX|]reviews WHERE revstatus='1' AND revproductid=p.productid AND revstatus='1') AS numreviews,
	(SELECT brandname FROM [|PREFIX|]brands WHERE brandid=p.prodbrandid) AS prodbrandname,
	(SELECT COUNT(imageid) FROM [|PREFIX|]product_images WHERE imageprodid=p.productid) AS numimages,
	(SELECT COUNT(discountid) FROM [|PREFIX|]product_discounts WHERE discountprodid=p.productid) AS numbulkdiscounts
	FROM [|PREFIX|]products p
	LEFT JOIN [|PREFIX|]product_images pi ON (pi.imageisthumb=1 AND p.productid=pi.imageprodid)
	WHERE ".$productSQL."
";

	// Begin View Hidden Products Mod
	if(!isset($GLOBALS['ISC_CLASS_ADMIN_AUTH'])) { $GLOBALS['ISC_CLASS_ADMIN_AUTH'] = GetClass('ISC_ADMIN_AUTH'); }
	// If the user has product editing capability, they can see the product when it's not visible on live store.
	if(!$GLOBALS['ISC_CLASS_ADMIN_AUTH']->HasPermission(AUTH_Edit_Products)) {
		$query .= " AND p.prodvisible='1'";
	}
	// End View Hidden Products Mod

Now you can preview your products!

Now, any user with the permission to edit products will be able to see products that are not visible to users in the store.

These types of small changes make the Interspire Shopping Cart an even better product.

Any other things you’d like to see made possible using Interspire Shopping Cart?

Related posts:

  1. Add ‘Customers Also Purchased’ to the Cart Page on Interspire Shopping Cart
  2. How to Add an `Edit Product` Link for Interspire Shopping Cart
  3. Improve Interspire Shopping Cart Search with Smart Redirections

Generate CSS Body Classes in Interspire Shopping Cart

Interspire CSS Body Class

If you’re used to WordPress’ body_class() function, this post for you.

Working with WordPress, it’s easy to get accustomed to some of its nice features, like the body_class() function introduced in WP 2.8. When working with Interspire Shopping Cart, I wanted the same level of information added to the page’s <body> tag.

Let’s do this in three stages:

1. Generate the body class

Starting from Dave Beck’s great canonical link module, I modified the code to create a list of classes based on what page is being viewed. This provides a lot of great information:

  • Brand
    • Brand ID
    • Brand name
  • Category
    • Category ID
    • Category Name
  • Home
  • Page
    • Page ID
    • Page Name
  • Sorted/Filtered/Paginated
    • Shop by Price
    • Tag
    • Sort type
    • Page number
  • Checkout/Account
    • Cart
    • Gift Certificate
    • Login
    • Search
    • SSL
    • Wishlist

This is very helpful stuff for custom styling using CSS.

Add to the bottom of the /lib/general.php file:

function BodyClass() {
	$bodyClass = array();

	if(isset($GLOBALS['ISC_CLASS_BRANDS'])) {
		$bodyClass[] = 'brand';
		$bodyClass[] = "brandID-".$GLOBALS['ISC_CLASS_BRANDS']->GetId();
		$bodyClass[] = "brandName-".$GLOBALS['ISC_CLASS_BRANDS']->GetBrandName();
	}

	if(isset($GLOBALS['ISC_CLASS_CATEGORY']) && isset($GLOBALS['CatId'])) {
		$bodyClass[] = 'category';
		$bodyClass[] = "catID-{$GLOBALS['CatId']}";
		$bodyClass[] = "catName-".$GLOBALS['ISC_CLASS_CATEGORY']->GetName();
	}

	if(isset($GLOBALS['ISC_CLASS_INDEX'])) {
		$bodyClass[] = "home";
	}

	if(isset($GLOBALS['ISC_CLASS_PRODUCT']) && $GLOBALS['ISC_CLASS_PRODUCT']->GetProductId() > 0) {
		$bodyClass[] = 'product';
		$bodyClass[] = "productID-".$GLOBALS['ISC_CLASS_PRODUCT']->GetProductId();
		$bodyClass[] = "productName-".$GLOBALS['ISC_CLASS_PRODUCT']->GetProductName();
	}

	if(isset($GLOBALS['ISC_CLASS_PAGE']) && !isset($GLOBALS['ISC_CLASS_INDEX']) && $GLOBALS['ISC_CLASS_PAGE']->GetPageId() > 0) {
		$bodyClass[] = 'page';
		$bodyClass[] = "pageID-".$GLOBALS['ISC_CLASS_PAGE']->GetPageId();
		$bodyClass[] = "pageName-".$GLOBALS['ISC_CLASS_PAGE']->GetPageTitle();
	}

	if(isset($GLOBALS['PriceMin']) && isset($GLOBALS['PriceMax'])) {
		$bodyClass[] = 'price';
		$bodyClass[] = "shopByPrice";
	}

	if(isset($GLOBALS['ISC_CLASS_TAGS'])) {
		$bodyClass[] = 'tag';
		$bodyClass[] = "productTags";
	}

	if(isset($_REQUEST['page']) && !empty($_REQUEST['page'])) {
		$bodyClass[] = 'paginated';
		$bodyClass[] = 'page'.(int)$_REQUEST['page'];
	}

	if(isset($_REQUEST['sort']) && !empty($_REQUEST['sort'])) {
		$bodyClass[] = 'sort';
		$bodyClass[] = 'sort'.ucfirst($_REQUEST['sort']);
	}

	$current_url = $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];

		$noindex_url = str_replace("http://", "", $GLOBALS['ShopPathNormal'].'/cart.php');
		if($current_url == $noindex_url) {
			$bodyClass[] = "cart";
		}

		$noindex_url = str_replace("http://", "", $GLOBALS['ShopPathNormal'].'/giftcertificates.php');
		if($current_url == $noindex_url) {
			$bodyClass[] = "giftCertificates";
		}

		$noindex_url = str_replace("http://", "", $GLOBALS['ShopPathNormal'].'/login.php');
		if($current_url == $noindex_url) {
			$bodyClass[] = "login";
		}

		$noindex_url = str_replace("http://", "", $GLOBALS['ShopPathNormal'].'/search.php');
		$split_url = explode('?', $current_url);
		$split_url = $split_url[0];
		if($split_url == $noindex_url) {
			$bodyClass[] = "search";
		}

		$noindex_url = str_replace("http://", "", $GLOBALS['ShopPathNormal'].'/login.php?from=wishlist.php%3F');
		if($current_url == $noindex_url) {
			$bodyClass[] = "wishList";
		}

		if(($GLOBALS['ISC_CFG']["UseSSL"] >= 1) && ($_SERVER['HTTPS'] == 'on')) {
			$bodyClass[] = "ssl";
		}
	$i = 0;
	foreach($bodyClass as $class) {
		$class = preg_replace('/\%[0-9]{2}/', '', $class); //mixed pattern, mixed replacement, mixed subject [, int limit [, int &count]])
		$class = str_replace(array('+','\'',' ','<','>','&'),'', $class);
		$bodyClass[$i] = $class;
		$i++;
	}
	$bodyClass = implode(' ', $bodyClass);

	// WordPress integration
	if(function_exists('get_body_class')) {
		$wpBodyClass = get_body_class();
		$wpBodyClass = implode(' ', $wpBodyClass);
		$wpBodyClass = str_replace('home', '', $wpBodyClass);
		$wpBodyClass = trim($wpBodyClass);
		if(!empty($WPBodyClass)) {
			$bodyClass .= ' blog wordpress '.$wpBodyClass;
		}
	}

	return $bodyClass;
}

2. Generate the global variable `BodyClass`

Since code placed in general.php is available to every script in the cart, we can use the result of the function in the script that generates the website’s <head>, HTMLHead.php. We’re going to create a global variable named BodyClass, and add it to our template.

Add to the bottom of the /includes/display/HTMLHead.php file:

$GLOBALS['BodyClass'] = ' class="'.BodyClass().'"';

3. Add to your template

Now the not-terribly-fun part: in every template file, find <body> and replace with <body%%GLOBAL_BodyClass%%> — you may need to go into the __master folder to do this, depending on your setup.

This will generate CSS classes like this: <body class="category catID-123 catName-Example">, and will give you microscopic control over your template’s styling.

How would you do it?

Manually adding the `BodyClass` variable into each template is cumbersome, but the only other way to do it is to use ob_start() and process the page before it’s displayed to the browser, and that would add load time. Any other ideas on how to achieve this?

Related posts:

  1. Add ‘Customers Also Purchased’ to the Cart Page on Interspire Shopping Cart
  2. How to Add an `Edit Product` Link for Interspire Shopping Cart
  3. Preview Hidden Products in Interspire Shopping Cart

Improve Interspire Shopping Cart Search with Smart Redirections

Good search results are magical

I am always impressed when a website’s search goes where I want and finds what I expect it to. When trying to find a specific product by SKU in Interspire, you will be presented with a search result that shows the product you’re looking for first. But this is not good enough, as it adds an extra click in the process.

If your users are specific enough to type in an exact product name, brand name, product SKU or product ID, you better get them to the product they want, right away — they’re likely to buy! I don’t want to show them a search results page, I want them to see the product or brand page itself.

If it’s a damn good match, send’em along!

This script will redirect users if there’s a good reason to.

  • Products
    • Exact product name match (case-insensitive)
    • Exact product SKU match
    • Exact product ID match
    • “Good’nuf” product match: if there’s only one product result, and that result has a relevance score of 75 or above
  • Brands
    • Exact brand name match (case-insensitive)

Installation of the Smart Search Redirection mod

Open the class.products.php, found at includes/classes/class.products.php. Find the searchForItems() function (near line 1160), and above return $products; at the end of the function, insert the following code:

/*
 * Begin Smart Search Redirection mod
 */
$redirect = false;

// Product redirect
foreach($products as $row) {
	if(	trim(strtolower($searchQuery['search_query'])) == trim(strtolower($row['prodcode'])) ||  // Query = SKU
		trim(strtolower($searchQuery['search_query'])) == trim(strtolower($row['productid'])) || // Query = Product ID
		trim(strtolower($searchQuery['search_query'])) == trim(strtolower($row['prodname'])) || // Query = Product Name
		$row['score'] > 75 && sizeof($products) == 1 // Relevance is good, and there's only one product result
	) {
		$redirect = ProdLink($row["prodname"]);
	}
}

if(empty($redirect)) {
	// Generate list of brand names
	foreach($products as $p) { $brands[] = $p['prodbrandid']; }
	$brandQuery = '"'.implode('" OR brandid="', array_unique($brands)).'"'; // Group brands by ID, generate query string
	$query = sprintf("select brandname from [|PREFIX|]brands where brandid=$brandQuery", $p['prodbrandid']);
	$result = $GLOBALS['ISC_CLASS_DB']->Query($query);

	// Brand name match redirect
	while($brand = $GLOBALS['ISC_CLASS_DB']->Fetch($result)) {
		if(trim(strtolower($searchQuery['search_query'])) == trim(strtolower($brand['brandname'])) && $redirect === false) {
			$redirect = BrandLink($brand["brandname"]);
		}
	}
}

// If there's a redirection found, do it up!
if(!empty($redirect)) {
	ob_end_clean();
	header("Location: $redirect");
	die();
}
/*
 * End Smart Search Redirection mod
 */

Ahh, nothing like better search!

Now that your search is taking users where they want to go, your user satisfaction should go up, and hopefully your sales and conversion rate!

Let me know if you have improvements to this code, and what your experience has been with it.

Related posts:

  1. Preview Hidden Products in Interspire Shopping Cart
  2. Add ‘Customers Also Purchased’ to the Cart Page on Interspire Shopping Cart
  3. Interspire Shopping Cart — Add a Brands Drop-Down Menu

Page 1 of 212»
YM : Frans Pekasa
twitter : franscirebon
Haloo …
Nama saya Frans S Pekasa, Saya bukan pakar seo dan juga bukan konsultan seo, saya hanya orang biasa. Jangan bandingkan saya dengan ali akbar, hendri susanto dan lainya. Saya cuman ingin berbagi ilmu tentang internet marketing, search engine optimization.
email : frans@frans.co.id
HP : +628122208998