<?xml version="1.0" encoding="utf-8"?>
<!-- generator="FeedCreator 1.8.0-dev (info@mypapit.net)" -->
<rss version="2.0"  xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>WinWorld Blog - Web Marketing Tips</title>
        <description><![CDATA[Web marketing tips learned over 10 years of web development.]]></description>
        <link>http://www.winworld.cc/</link>
        <lastBuildDate>Sat, 25 May 2013 02:33:10 GMT</lastBuildDate>
        <generator>FeedCreator 1.8.0-dev (info@mypapit.net)</generator>
        <image>
            <url>http://www.winworld.com/templates/winworld/images/logo.gif</url>
            <title>WinWorld</title>
            <link>http://www.winworld.cc/</link>
            <description><![CDATA[WinWorld]]></description>
        </image>
		<atom:link href="http://www.winworld.cc/index.php?option=com_ninjarsssyndicator&amp;feed_id=1&amp;format=raw" rel="self" type="application/rss+xml" />        <item>
            <title>Migrating websites from dedicated cpanel servers to Rackspace Cloud</title>
            <link>http://www.winworld.cc/blog/17-blog/269-migrating-websites-from-dedicated-cpanel-servers-to-rackspace-cloud.html</link>
            <description><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
</head>
<body>
<h3><strong>Background</strong></h3>
<p>As many in the web design industry would know, if you're in the web design or development business, you're also defacto in the hosting/domain business. Some web companies choose to pass that role back on the client, advising them where to buy hosting. Other web design agencies will get a reseller account with a control panel host (e.g. Plesk or cPanel) such as Hostgator or Bluehost. That was our story many years ago - we got a reseller account at a cpanel host. What we ran into with that was a lack of control. We weren't able to install the php packages to suit our needs and had to dance around server config such as upload limits. One day we had a huge fiasco with a shared ip address that was directly linked into a newsletter mailing and we couldn't get the ip address back. That stress was enough for us and shared cpanel hosting.</p>
<p>So we moved to dedicated hosting. That brought a whole other set of challenges. We had to learn all about full administration of a linux server. For a while we continued to use cpanel but eventually even got frustrated with cpanel's limitations and just went to manual configuration. When we surveyed clients we found that the majority of our clients didn't even use the control panel and even found it a hassle. So in order to make changes to hosting config, clients would just submit tickets and we'd take care of it. We did find a very small percentage though that did still want a control panel so we always had bringing that back somehow in the back of our minds.</p>
<p>Another issue with dedicated hosting (where you rent a full box at a data center) is having a single point of failure. We had single disk servers to start with and then felt it would be better to move to raid systems. We had raid systems with Layered Tech and that was a nightmare. They seemed to just continuously reuse old hard drives. We had a major windows server crash three times in six months. That was enough for us there. We also had dedicated servers with Server Beach. Their support was better but unfortunately we had more hardware failures on raid5 that we did on single disk servers.</p>
<p>The hardware was the main aspect that prompted us to investigate cloud hosting. In the cloud sites serving load is spread across hundreds of servers. If one goes down it can easily be replaced without downtime. With dedicated servers we had to know and depend on our backup mechanisms as our life depended on it. If a server went down it certainly meant 48 hours doing a complete reload of all files and sites on the server. So being able to rest a bit more peacefully in regards to downtime was alluring to us.</p>
<p>Cloud hosting would also reintroduce a limited control panel for those clients who wanted one but would still give us the ability to manage advanced settings at a higher level. Even though we had staff in house that knew how to admin linux servers, having a control panel also meant that folks in admin could setup accounts or delete accounts if needed.</p>
<h3><strong>How to migrate from linux/cpanel to rackspace</strong></h3>
<p>This isn't meant to be a definitive guide on how to move websites to rackspace cloudsites but it is a compilation of suggestions we accumulated along the way. This guide is also a bit high-level / not detailed. You need a base of knowledge to do this. If you can't make these suggestions work then you may want to hire a more experienced technician to do this for you.</p>
<p>To us it seemed that there would be phased migration.</p>
<ul>
<li>Step One: Migrate all DNS to zones to Rackspace AS THEY ARE. This means that you can repoint your hosting company's name servers to Rackspace's nameserver IPs and then all your clients DNS will also be performed from Rackspace BUT this is before you've moved ANY of the sites over. The DNS will actually point all of the domains BACK to your current main cpanel/dedicated servers.</li>
<li>Step Two: After migrate all the actual site files and databases.</li>
<li>Step Three: Switch the A record IP address for each website over from your old dedicated server IP to the Rackspace IP, essentially taking the site live.</li>
</ul>
<p>If you manage DNS through a third party like your domain registrar then you can probably skip the whole DNS phase.</p>
<h3><strong>Migrating DNS</strong></h3>
<p>If you have a bare dedicated server or a cpanel dedicated server, chances are you have one of your dedicated servers also serving as your primary name server. If you're running cpanel, you're probably using bind (even if you don't know it) or if you don't have cpanel then you know you're running bind (because you have to manually edit named.conf to add domains).</p>
<p>So why do the DNS first? We use ns1/2.ourhostingcompany.com as our name servers. We have hundreds of domains registered. We've registered most of them but 10-20% are registered by the clients themselves. They all are pointed at ns1/2.ourhostingcompany.com though. We control that domain and we get to set the IP addresses of the name servers for ns1/2.ourhostingcompany.com. With moving to rackspace we could spend countless hours going and updating all the domains to point to ns1/2.stabletransit.com or we could just leave them and reroute the traffic to rackspace's nameservers.</p>
<p>We actually wanted to migrate all websites files and databases themselves first and then the DNS. The first way we tried this essentially failed. We went into our named.conf and made our nameserver an open forwarder. We set forward {any;}. The plan was to move the site files and database and make sure the website was working at Rackspace, then after we'd confirmed that each site had successfully migrated to Rackspace just go in their zone file on our name server and say "forward all DNS requests for this domain to Rackspace." This failed because when we did that rackspace's name servers thought they were authoritative yet our name servers were still thinking they were authoritative so there was confusion.</p>
<p>The next step seemed to be to ensure all our domain zones were replicated at rackspace and then completely repoint ns1/2.ourhostingcompany.com to rackspace's nameserver's IP addresses. And THEN we'd move the sites.</p>
<h3><strong>Getting ready</strong></h3>
<p>This was a huge task. Again we have 100s of accounts. The first thing we had to do was get someone to manually set up a client in Rackspace for each client we had. Rackspace, if you're reading this, please create an API that lets you programmatically add clients and websites to rackspace cloudsites. It would have sped things up for us massively. Having our admin staff do this in their spare time probably took 2-3 weeks. They would create the client, then create the website under the client, and then they would create the database, the username for the database, the database password and even take note of the ip address and hostname for the database. Most of our site's have databases so we needed to do this.</p>
<p>There's a control panel in Rackspace for all of this and it doesn't need much explaining. Once all that groundwork was laid we had to figure out how to transfer all the custom records in our DNS server to Rackspace's nameserver.</p>
<p>For example, some of our client have their MX records set to Google apps mail, some use paid 3<sup>rd</sup> party mail services. Some clients have custom cnames, etc. We didn't want human beings to have to sit there and manually copy and paste 1000s of domain record entries from our nameserver over to Rackspace's control panel (its slow if you're doing this type of repetitive task). Luckily Rackspace DOES have a DNS API. It's not hugely documented.</p>
<h3><strong>The actual code to migrate DNS from bind to rackspace via the api </strong></h3>
<ul>
<li>Here's the base documentation: <a href="http://docs.rackspace.com/cdns/api/v1.0/cdns-devguide/content/index.html"> http://docs.rackspace.com/cdns/api/v1.0/cdns-devguide/content/index.html </a></li>
<li>We started with a PHP toolkit here: <a href="http://www.coolgeex.com/rackspace-cloud-dns-api-php-class/">http://www.coolgeex.com/rackspace-cloud-dns-api-php-class/</a></li>
<li>After the fact we also found this more complete PHP system: <a href="http://donotexec.com/2011/10/rackspace-cloud-dns-api-interface/">http://donotexec.com/2011/10/rackspace-cloud-dns-api-interface/</a></li>
</ul>
<p>The coolgeex one provides the rackDNS.php class and also a sample.php to show how to interact with the API. Using the sample.php we wrote our own script to do what we wanted. The coolgeex one didn't work immediately for us. We found there was some issue with curl and https. We had to set a curl parameter to ignore https problems and then it worked fine.</p>
<p>The idea was to essentially go through each domain, delete the default zone created by Rackspace and replace it with our zonefile. Of course if you run bind, all your zonefiles are located in /var/named or /var/named/chroot/var/named. The problem is that Rackspace only accepts FQDN format zone files as input so if some of your zone files are relative, it won't work. E.g., bind will let you point multiple domains at one zone file and just say</p>
<p style="margin-left: 30px;">A xx.xx.xx.xx <br /> sub CNAME whatever.domain.com ;subdomain</p>
<p>But Rackspace needs absolute zone files like this:</p>
<p style="margin-left: 30px;">Domain.com A xx.xx.xx.xx <br /> sub.domain.com CNAME whatever.domain.com</p>
<p>If you have a mixture of relative zone files there is a way to get bind to spit all the zone files back out as absolute zones. Here's a link on how to do that: <a href="http://ubuntuforums.org/showthread.php?t=903651">http://ubuntuforums.org/showthread.php?t=903651</a></p>
<p>Basically it creates all your nameserver's domain zones in one file. You can then use PHP to loop through those zones and work with the Rackspace DNS API.</p>
<p>The second issue we had was account IDs. If you create a subclient in RS and then a domain under that client, if you connect to the DNS API and then say "show me all the domains" it will only show ones in YOUR account, not sub-client domains. In order to see sub-client domains, you have to connect to the api using the sub-client's ID number. There's more info on this topic at the donetexec link above. So consequently, what we needed was another file that mapped all our domains to client id's at rackspace.</p>
<p>Once we had these two pieces we could have a php script</p>
<ol>
<li>Read in all the domains from the bind dump and start looping through them</li>
<li>For each domain connect to the dns api using the client's id<ol>
<li>Wipe what RS had there by default</li>
<li>Load our zone file</li>
</ol></li>
</ol>
<p>I've provided the code that we ran with the coolgeex rackDNS.php.</p>
<p>{codecitation class="brush:php" height="300px"}</p>
<p>&lt;?php<br />/**<br />*<br />* Rackspace DNS PHP API sample.php<br />* @author Alon Ben David<br />* @copyright CoolGeex.com<br />*/</p>
<p>require_once "rackDNS.php";</p>
<p>//credentials<br />$rs_user = 'YOURRSUSERNAME';<br />$rs_api_key = 'YOURRSAPIKEY';</p>
<p>&nbsp;</p>
<p>//first load all the codes we have for domains<br />$codes = array();<br />include('codes.php');</p>
<p>include('domain-dump.php');</p>
<p>&nbsp;</p>
<p>//now lets load the zones into an array<br />$temp = explode(";", $tempstring);</p>
<p>unset($tempstring);</p>
<p>$zones=array();</p>
<p>&nbsp;</p>
<p>//now lets rework the array with the key as domains<br />foreach($temp AS $zone)<br />{<br />//get the domain name from the first bit<br />$domain = substr($zone,0,strpos($zone," "));<br />$domain = str_replace(array(" ","\t","\n","\r"),"",$domain);<br />$domain = substr($domain,0,-1);<br />$zones[$domain]=$zone;<br />}</p>
<p>unset($temp);</p>
<p>$domainsdone = array();<br />$domainsmissingcode = array();<br />$domainserror = array();</p>
<p>if ( isset( $_COOKIE["domainsdone"] ) ) { $domainsdone = explode("|",$_COOKIE["domainsdone"]); }<br />if ( isset( $_COOKIE["domainsmissingcode"] ) ) { $domainsmissingcode = explode("|",$_COOKIE["domainsmissingcode"]); }<br />if ( isset( $_COOKIE["domainserror"] ) ) { $domainserror = explode("|",$_COOKIE["domainserror"]); }</p>
<p>&nbsp;</p>
<p>//now lets loop through the zones and see which domains we have codes for.<br />//if we have a code, clear all records in that zone and load the zone file we have</p>
<p>$count = 0;</p>
<p>foreach($zones AS $domain =&gt; $zone)<br />{</p>
<p>if( $codes[$domain]!="" AND !in_array($domain,$domainsdone) AND !in_array($domain,$domainserror) )<br />{<br />//we've got the code, now lets do this.<br />$count++;</p>
<p>//establish connection<br />$dns = new rackDNS($rs_user,$rs_api_key,'US',$codes[$domain]); //($user, $key, $endpoint = 'US') $endpoint can be UK or US</p>
<p>//echo "Working with ".$domain." which has a code of ".$codes[$domain]."\n\r";</p>
<p>//get the domain for this code<br />$tempdomains = $dns-&gt;list_domains(50,0);<br />$domainslist = $tempdomains['domains'];</p>
<p>//print_r($tempdomains);<br />//unset($tempdomains);</p>
<p>//loop through the domains for this account and ensure we grab the right info for the right domain<br />foreach($domainslist AS $theirdomain)<br />{<br />if (strtolower($theirdomain['name']) == strtolower($domain))<br />{<br />$domainID = $theirdomain['id'];<br />$domainName = $theirdomain['name'];<br />}<br />}</p>
<p>//if (!$domainID) die("domain missmatch for ".$domain." and code ".$codes[$domain].". Halting.");</p>
<p>//should probalby check if $domain and $domainName matches<br />//if so we just delete it<br />if( strtolower($domain) == strtolower($domainName) ) $delete = $dns-&gt;delete_domains($domainID);</p>
<p>//wait a bit because deleting takes a while<br />sleep(3);</p>
<p>//now lets import it according to our zone<br />$import = $dns-&gt;domain_import($zone);</p>
<p>sleep(3);</p>
<p>if($import['status']=='COMPLETED' OR $import['status']=='RUNNING') {$domainsdone[] = $domain; }<br />else {</p>
<p>$domainserror[]=$domain;</p>
<p>if(!isset($_GET['dontshowerror']))<br />{<br />echo "&lt;pre&gt;Working with ".$domain." whose client has a code of ".$codes[$domain]."<br />and whose ID is ".$domainID."\n\r";</p>
<p>echo "All of their domains are:\n\r";</p>
<p>print_r($tempdomains);</p>
<p>echo "This is the result of the delete:\n\r";</p>
<p>print_r($delete);</p>
<p>echo "This is the result of the import:\n\r";</p>
<p>print_r($import);</p>
<p>die;<br />}</p>
<p>}</p>
<p>if ($count &gt;=500) break;</p>
<p>} elseif (!in_array($domain,$domainsmissingcode) AND !in_array($domain,$domainsdone) AND !in_array($domain,$domainserror) ) {<br />$domainsmissingcode[] = $domain;</p>
<p>}</p>
<p>}</p>
<p>setcookie("domainsdone", implode("|",$domainsdone), time()+86400);<br />setcookie("domainsmissingcode",implode("|",$domainsmissingcode), time()+86400);<br />setcookie("domainserror",implode("|",$domainserror), time()+86400);</p>
<p>echo '&lt;html&gt;&lt;head&gt;&lt;meta http-equiv="refresh" content="30"&gt;&lt;/head&gt;&lt;body&gt;';</p>
<p>echo "&lt;pre&gt;";</p>
<p>print_r($import);</p>
<p>echo "Domains that are done:\n";<br />print_r($domainsdone);<br />echo "\n";<br />echo "No codes for these domains:\n";<br />print_r($domainsmissingcode);<br />echo "Error occured when importing zones for these domains:\n";<br />print_r($domainserror);</p>
<p>?&gt;</p>
<p>{/codecitation}</p>
<p>Note that you will have to modify to suit you. I'm not going to provide a copy of our domain dump from bind because that is a very standard format of file, but I will show a sample of how we loaded the "codes" (or client id numbers corresponding to each domain).</p>
<p>&lt;?php <br /> $codes["domain1.com"] =123123; <br /> $codes["domain2.com"] =123124; <br /> ?&gt;</p>
<p>We wrote the script to be executed by browser but it could be executed by cron. We wrote it to process X domains per run and then stop. We also wrote it to meta-refresh to keep running until all the domains had been processed. We decided to store the domains that had been processed in a cookie. We just didn't want to mess around with writing files to the server or setting up a database just for this one function.</p>
<p>One thing to note here. RS still gave errors on trying to import some of our domains even though they were in absolute format. What we found was that TTL times below 300 seconds would be rejected. So where we'd set TTLs on our server very low, those domain imports failed until we manually updated the domain dump file with higher TTLs. RS DNS imports failed for other reasons too. We modified the rackDNS.php file to show more detailed error results back from the RS DNS API to help diagnose this. It doesn't do it by default. See "show detail" in the RS DNS API documentation for more info.</p>
<p>Now that DNS had been migrated, essentially what we had was a complete mirror of our DNS server at Rackspace. All the domains pointed back to our current hosting server, not to rackspace itself. We then logged into our registrar, went under "register nameserver" and updated the IP addresses of our nameserver to those IPs of Rackspace's nameservers instead of ours. Everything kept running without a hitch.</p>
<h3><strong>Step two: move the files, databases and update config files</strong></h3>
<p>This part should be a little easier for most folks who have done a bit of hosting reselling to understand. The simple process is to use FTP to upload sites, use MySQL to upload databases and then update config files so sites at RS connect to RS's mysql servers.</p>
<p>We also chose to script this into one step. If you run cpanel there is some consistency in the way your accounts are setup, even if you don't, you have some consistency.</p>
<p>This is the basic perl script we used:</p>
<p>{codecitation class="brush:php" height="300px"}</p>
<p>#!/bin/bash</p>
<p>#push an account to rackspace, files, database, etc. <br />#NOTE THAT YOU have to update your server paths correspondingly</p>
<p>if [ -z "${11}" ]; then</p>
<p>echo 'Please supply arcuments after the script name in the following order'<br />echo '$1 = name of the home folder locally'<br />echo '$2 = username at rackspace'<br />echo '$3 = password at rackspace'<br />echo '$4 = the domain name' <br />echo '$5 = the local database'<br />echo '$6 = the remote database hostIP'<br />echo '$7 = the remote database username'<br />echo '$8 = the remote database password' <br />echo '$9 = the remote database name'<br />echo '$10 = the user number at rackspace'<br />echo '$11 = the remote database hostNAME'</p>
<p>exit</p>
<p>fi</p>
<p>#dump the database <br />mysqldump -uroot -pYOURMYSQLROOTPASS $5 &gt; /home/$1/$5.sql</p>
<p>#upload the database<br />mysql -h$6 -u$7 -p$8 $9 &lt; /home/$1/$5.sql</p>
<p>#compress everything<br />cd /home/$1/public_html/<br />tar cvf /home/$1/thesite.tar *</p>
<p>#upload it</p>
<p>ncftpput -u $2 -p $3 ftp2.ftptoyoursite.com /$4/web/content /home/$1/thesite.tar</p>
<p>#we need to make sure a 'decompress' php file makes it up</p>
<p>ncftpput -u $2 -p $3 ftp2.ftptoyoursite.com /$4/web/content /home/PATHTOWHEREYOURESTORINGTHISFILE/unpack.php</p>
<p>#now run it so the site is decompressed (this also removes the tar and index.html file)</p>
<p>wget <a href="http://$4.php5-22.dfw1-1.websitetestlink.com/unpack.php">http://$4.php5-22.dfw1-1.websitetestlink.com/unpack.php</a></p>
<p>{/codecitation}</p>
<p>&nbsp;</p>
<p>You need to install ncftpput on your server for this to work. Try yum install ncftpput or google.</p>
<p>The script needs you to supply all the details as command line parameters. So what we did was we had a spreadsheet of all the websites along with columns for things like ftp username, password, database name, mysql hostname, etc.</p>
<p>At first we just did an ncftpput -r, which would recursively upload all the files one by one. We then found this not to be working too well for speed so we moved to uploading a TAR file. We got a little creative and wrote a php file that we could also upload to the hosting space at rackspace and then trigger it remotely from the script using wget. The script would basically unpack the tar at rackspace.</p>
<p>&nbsp;</p>
<p>{codecitation class="brush:php" height="300px"}</p>
<p>&lt;?php</p>
<p>exec("rm index.html",$out,$retval);</p>
<p>exec("tar --keep-old-files -xvf thesite.tar",$out1,$retval1);</p>
<p>exec("rm thesite.tar",$out2,$retval2);</p>
<p>?&gt;</p>
<p>{/codecitation}</p>
<p>&nbsp;</p>
<p>If the site is large the tar fails to fully unpack within the 30 second timeout that rackspace allows. No worries though. Just --keep-old-files parameter. Wget will keep hitting the unpack.php and each time the untar happens, it will get further, finally unpacking all the files. Some large sites took 11-12 tries to fully unpack but they did work.</p>
<p>Also note in the script where it says "wget…" You'll have to edit that line to what ever websitetestlink.com address RS is generating for you. You could make the whole domain a command line parameter.</p>
<p>As I noted in the subheading above, the third part of this phase is to update all the config files. It's likely you're running a lot of wordpress, maybe some joomla, magento, drupal, etc. We got creative and actually included the edits for the config files in the script that was migrating.</p>
<p>Here's some sample code that edits a Joomla configuration.php (caution, your mileage may vary):</p>
<p>&nbsp;</p>
<p>{codecitation class="brush:php" height="300px"}</p>
<p>cp /home/$1/public_html/configuration.php /home/$1/public_html/tmp/configuration.php</p>
<p>#edit configuration.php<br />sed -i "/\$log_path/s/'.*'/'\/mnt\/stor3-wc1-dfw1\/MASTERRSACCOUNTID\/${10}\/$4\/web\/content\/logs'/" /home/$1/public_html/tmp/configuration.php</p>
<p>sed -i "/\$tmp_path/s/'.*'/'\/mnt\/stor3-wc1-dfw1\/MASTERRSACCOUNTID\/${10}\/$4\/web\/content\/tmp'/" /home/$1/public_html/tmp/configuration.php</p>
<p>sed -i "/\$host/s/'.*'/'${11}'/" /home/$1/public_html/tmp/configuration.php</p>
<p>sed -i "/\$user/s/'.*'/'$7'/" /home/$1/public_html/tmp/configuration.php</p>
<p>sed -i "/\$password/s/'.*'/'$8'/" /home/$1/public_html/tmp/configuration.php</p>
<p>sed -i "/\$db /s/'.*'/'$9'/" /home/$1/public_html/tmp/configuration.php</p>
<p>#upload config files because we customized those and need to overwrite remote old with new</p>
<p>ncftpput -u $2 -p $3 ftp2.ftptoyoursite.com /$4/web/content /home/$1/public_html/tmp/configuration.php</p>
<p>{/codecitation}</p>
<p>&nbsp;</p>
<p>We're using sed to edit the config file on the fly and then upload the version that correctly configured for RS to RS. Note that we put this at the end of the script after all the other stuff is done. There's probably a more graceful way to do the sed but we did what we could. This approach could be adapted for any type of config for "insert your open source script here."</p>
<h3><strong>Testing </strong></h3>
<p>The last thing to do after all this was to simply test the sites work. Just visit the websitetestlink in your browser. The thing about this whole process is that you'll hit various snags along the way. For example with the DNS migration various zones got stuck and we had to fix them. Then with transferring files, sometimes the write permissions on the configuration.php would be wrong and we'd have to fix that. It's just troubleshooting at that point.</p>
<p>A special note on SSL. Some sites of course will require SSL. There's no need to generate a new CSR from rackspace and get a new cert. Just simply copy the certificate files from the old server. You'll have to do a bit of research to find out where they are. First you'll have to find your httpd.conf. On a cpanel server it may be difficult to know where that actually is. It's been a while since I've worked with cpanel so I can't recall exactly. A common place is /etc/httpd/conf/httpd.conf. Once you're in that file check to see if the virtual host entry for the domain is in there. Or else check at the bottom of the file for the include statement. Its generally going to include a block of files like /etc/httpd/conf/vhosts/*.conf. Once you find where the actual vhost file is you can look at that. Look for an entry for "SSLCertificateKeyFile". Note the location of that file. Go and open the file and copy and paste the key over to Rackspace. Then also copy and paste the "SSLCertificateFile" over. Note that when you save the SSL at rackspace, based on the methodology described in this guide, it WILL take the site live immediately - because it's updating the A record for the domain.</p>
<p>Beware of HTACCESS. If you're site such as Joomla or Magento is using SEF urls with htaccess rewrite - you MUST set the RewriteBase in htaccess. If you don't the site will not show. You also may find it extremely valuable to add the following values to the end of the htaccess file. It will enable your clients to upload larger files via their admins.&nbsp;</p>
<p>php_value upload_max_filesize 50M<br />php_value post_max_size 50M<br />php_value max_execution_time 200<br />php_value max_input_time 200</p>
<p>We actually automated this too by tagging this code to the very end of our migration scripts:&nbsp;</p>
<p>&nbsp;</p>
<p>{codecitation class="brush:php" height="300px"}</p>
<p>sed -i "s/# RewriteBase/RewriteBase/g" /home/$1/public_html/.htaccess</p>
<p>echo "</p>
<p>php_value upload_max_filesize 50M<br />php_value post_max_size 50M<br />php_value max_execution_time 200<br />php_value max_input_time 200" &gt;&gt; /home/$1/public_html/.htaccess</p>
<p>ncftpput -u $2 -p $3 ftp2.ftptoyoursite.com /$4/web/content /home/$1/public_html/.htaccess</p>
<p>{/codecitation}</p>
<p>&nbsp;</p>
<p>Beware of include paths! If you have code in your old sites that have something like "include('/home/whatever/blah/file.php')" that will fail. Not only that, it will disable php error reporting so the error is not shown to you. I'm not sure why error reporting is disabled for this type of error but I'm thinking that it's a security thing? Maybe they don't want people to be able to probe server root paths and publicly show what paths exist or not. If you have a blank site - check the includes.</p>
<h3><strong>Switchover </strong></h3>
<p>So once the site is working its time to switch it over. Because we created placeholders for all the sites using the RS control panel to start with, then we moved all the current DNS zones over to RS via the API, then we repointed the hostingcompany's dns servers to RS's Nameserver's IP addresses - RS's Nameservers are still pointing back to the old hosting servers. The only thing to do is to go into RS's control panel, into the client's website and update the A record back to the default it would have been set at before we overwrote them with the custom zone entries (that, again, point back to the old dedicated servers). So HOW do we know what the IP is at RS???</p>
<p>Do a dig on the "websitetestlink.com" url supplied in the General tab of the website settings. If you dig that, it will give you the correct A record. If you also have an FTP cname for the domain, you may want to point that to <a href="http://www.winworld.cc/ftp://ftp2.ftptoyoursite.com/">ftp2.ftptoyoursite.com</a></p>
<p>Don't forget parked domains! When you migrate the sites, don't forget to also migrate the alias/addon domains. Putting an alias domain on a website at rackspace is a bit weird. See if you can figure out how to do it, but if not, chat support and they'll tell you. I'm not writing in here how it's done because I just want to make a point that I think this part of the process is a bit funky at RS.</p>
<p>If you migrated your aliased domains to RS before migrating the sites, RS will not let you reset their A records via the API. To repoint the alias domains over to RS, you have to use the "donotexec" toolkit above. Its easy to forget aliased domains but clients will call up at some point asking where their other domains aren't working.</p>
<p>If you refrained from actually going to theclientsdomain.com in your browser, you can actually go to it now and it SHOULD direct you to the client's site at RS so you can further test. The reason for this is that if you haven't directly hit the client's domain recently, then you don't have their IP cached locally and your computer/router is going to go grab the fresh IP. If you're not sure then open up /etc/system32/drivers/etc/hosts file and "hardcode" the new RS IP in for the clients domain and visit it. Your computer will definitely be showing the client's site at RS so you can test it. If you're really unsure, make a change to the site via FTP or websitetestlink.com and see if you can see the change.</p>
<p>The last thing you want is to do a switchover but then get a call from the client that their site is in actual fact, down.</p>
<h3><strong>Conclusion</strong></h3>
<p>I hope some have found this guide helpful. I wrote it because migrating from a dedicated server to a cloud environment can be a real bear. What makes it difficult is the control panels and lack of api to speed up the process. You have to do so much work manually. If it were migrating from one dedicated server to another, it would just be a matter of copying all the files and doing general config. If this helped you please feel free to comment below.</p>
</body>
</html>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Thu, 22 Mar 2012 00:56:46 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/17-blog/269-migrating-websites-from-dedicated-cpanel-servers-to-rackspace-cloud.html</guid>
        </item>
        <item>
            <title>Using Eggdrop App as a virtual yard sale</title>
            <link>http://www.winworld.cc/blog/17-blog/258-using-eggdrop-app-as-a-virtual-yard-sale.html</link>
            <description><![CDATA[<p><img style="margin-right: 20px; margin-bottom: 20px; float: left;" alt="eggdrop" src="http://www.winworld.cc/images/blog/eggdrop.png" height="64" width="285" />I've sold my stuff on a number of yard sales throughout my life as I'm sure many have. One thing I never liked was all the effort involved. It don't like how you have to pick everything up and take it outside and potentially tag it. Then if it doesn't sell, you bring it back inside or take it to the thrift shop or dump. Or worse yet, if it rains you run around like crazy with tarps, etc. All this to make a couple hundred bucks (depending on what you're selling).</p>
<p>If you don't want to have a yard sale, there's always eBay. To me, eBay only seems to be for certain things. If you have something unique, valuable and shippable, then eBay is the way to go. A custom guitar for example. If it's a keyboard and mouse combo for $2.50 then eBay is not the way to go since there are 1000s of other sellers and you won't sell your item. The alternative is craigslist. You get to deal locally. To their credit, craigslist has kept things simple. You put in a title, price, description, place and pictures. To me this still seems a little harder than it needs to be. You've got to verify who you are and there are all these rules for posting stuff. A drawback of craigslist is that it seems you only have network marketers and dating services on there any more. They have not evolved.</p>
<p><strong>Here's what I want... </strong></p>
<p>I want a mobile app where <span style="text-decoration: underline;">all I have to do is take a picture of what I'm selling. That is litterally it.</span> One step. If I want to title and price it, fine, its easy enough to do that quickly. Mobile phones have camera's built in so it just seems like the most logical decision to use them to make it easier to sell stuff. Recently the app "Eggdrop" came out. It seems to be pretty close to what I want. This article is a review of the app plus some things that I did to extend it's functionality into what I wanted.</p>

<p> </p>
<p>The experience with Eggdrop is as follows, you download the app to your phone, you fire it up and either create an account or connect via Facebook/Twitter. The first thing you're presented with is any items for sale near you. Since it's a new app, it may be that no one near you is using it to sell things so the list may be empty.</p>
<p><span style="text-decoration: underline;">The big question in my mind was - does EggDrop list your items for sale on the web?</span> Seeing the desert of ecommerce within their app was a deterent for me using it. If my only avenue for selling something is through their app, I will not sell anything, because not many others use a new app. That is a critical mass problem many many app developers have. Thats the way it is. But... I wanted to test list some items to see if EggDrop would give me some sort of link to a listing page for my account with them.</p>
<p>So I started listing items. I took a picture of my foot and listed it for $100. It was really easy. You take the picture, you put in your title and price and boom. You're done. I loved the simplicity.</p>
<p>I listed another item, a rocking chair. Same deal. I noticed that within the app, after I'd listed items, it would ask if I wanted to promote my sale to my friends on Twitter or Facebook. Bingo I thought - if it's letting me do this, it's going to be posting a web address that my friends can go look at my stuff for sale.</p>
<p>Essentially, I could use it to host the worlds easiest, come-whenever-you-want, 24-7, till-the-cows-come-home, VIRTUAL YARD SALE!</p>
<p>How easy is it to sit in your living room and just point a camera at stuff you're selling. This beats carting stuff out the front door - hands down.</p>
<p>So I clicked the option to promote my item. It took me to a web page with a picture of my item. There was my first name and low and behold, when I clicked that it too me to a listing of all MY items. This was getting really good.</p>
<p>The next day my wife and I set about snapping pictures and listing things we wanted to get rid of.</p>
<p>After we'd each gone around and listed about a dozen items each - I went to our sales listing pages on our accounts. <span style="text-decoration: underline;">Uh oh. Only four items were listed</span>. Apparently EggDrop only lists your most recent four sales items on their website. In order to give your friends a full list of items, you'd have to post links to all of your items individually.</p>
<p>This is what the single item page looks like:</p>
<p><img alt="eggdrop-single" src="http://www.winworld.cc/images/blog/eggdrop-single.png" height="368" width="497" /></p>
<p>This is what a multiple listing page looks like:</p>
<p><img alt="eggdrop-multi" src="http://www.winworld.cc/images/blog/eggdrop-multi.png" height="401" width="494" /></p>
<p>(Note the limit of four)</p>
<p><strong>Why would they limit it like this?</strong></p>
<p>I think the reason for doing this is to get more people to use their app. I would disagree however. They need to enable more of their database on the web. They need an autosensing IP locator and a map on their home page with dots. Of course the dots should just list items, not people. They also need to list all items on user's listing pages. I think they should also introduce categorization. Once I start listing dozen's of items on my listing page - I'm going to want a way to seperate books from furniture, for example. If someone wants to go ahead and make a purchase, they can then get the app.</p>
<p><strong>I started to think of a way around this</strong></p>
<p>I couldn't get so close to my lazy goal of a almost effort free, virtual yardsale, and then fail. The problem isn't that the items are not viewable on the web for sale, the problem is they are not listed all in one place. Some of the solutions to this that I thought of were... Maybe I could just make a list of URLs and post the on my blog or something. That would not be very attractive however. If I posted titles and pictures also, then that would be more effort than it even takes to post on eBay or Craigslist.</p>
<p>What could be done?</p>
<p>Normally a web service has some sort of "feed" - a feed that lets you pull listings and redisplay them elsewhere. EggDrop is pretty new so I could not find any feeds available.</p>
<p>EggDrop lets you post to Facebook - but Facebook is generally closed behind a login. Twitter however... that is public. So I thought, what if I post ALL of my sales to Twitter. Then I can search twitter and write a script to recombine all of my sale items onto one page.&nbsp;</p>
<p>So I wrote a PHP script that pulls my Twitter feed using my username. It goes through all my Tweets looking for the hashtag #quicksale</p>
<p>That is the hashtag that EggDrop attaches to all your promotions by default. It then pulls the link to the item out of the tweet.</p>
<p>It downloads the web page for that item. If the page is a listing page, it skips it. If the page is a canceled or expired item, it skips that too. What it does though is saves all the items that are available.</p>
<p>Finally it agregates all those items back into one listing page that looks very similar to the listing page that EggDrop provides (but without the four item limit). Here's a snapshot of the result (downsized):</p>
<p><img alt="eggdrop-agre" src="http://www.winworld.cc/images/blog/eggdrop-agre.png" height="693" width="570" /></p>
<p>There's more than four on the page.</p>
<p>My next issue was where to put this. I didn't want to confuse people. I wanted people to just think "this is eggdrop" and if they want to use the app or go further, just just click one of the links like you would on their normal website.</p>
<p>EggDrop has done a great job with this, so I put it on the domain eggdropped.com</p>
<p>The script works for anyone. Just use this format:</p>
<p style="text-align: center;"><span style="text-decoration: underline;"><span style="font-size: 14pt;"><strong>http://www.eggdropped.com/index.php?user=yourtwitterhandle</strong></span></span></p>
<p>I just want to be really clear, my fear with setting up this script on WinWorld.com or my blog was that I did not want to take away from EggDrop or all the hard work they've done. This is not my thing, it's their thing. I just grabbed my sale item listings and put them all on one page. I hope that more people find the web listings and start using the app because it's very easy to use. All the links on the listing page point back to EggDrop themselves. If anyone at EggDrop sees this and you have questions, please contact me.</p>
<p>My script (above) caches results for 24 hours before automatically renewing them. This is to ease hitting EggDrop's servers and also to speed up the page load. If you need to refresh the cache, just use the following URL format: http://www.eggdropped.com/index.php?user=yourtwitterhandle&amp;refresh=1</p>
<p>Although don't give this URL out because the page load will be too slow.</p>
<p>If you want to test it out, just follow this twitter search and build a page for a user there you see listing more than once: <a href="http://twitter.com/#%21/search/realtime/%23quicksale%20%40eggdropapp">http://twitter.com/#!/search/realtime/%23quicksale%20%40eggdropapp</a></p>
<p> </p>
<p> </p>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Tue, 20 Sep 2011 19:17:29 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/17-blog/258-using-eggdrop-app-as-a-virtual-yard-sale.html</guid>
        </item>
        <item>
            <title>Creating branching logic in multi-page RS Form Pro</title>
            <link>http://www.winworld.cc/blog/25-joomla/257-creating-branching-logic-in-multi-page-rs-form-pro.html</link>
            <description><![CDATA[<p>RS Forms is a great component. Its got all the hooks in the admin to be able to add any kind of advanced dynamic functionality that you want. A recent version of RS Form introduced the concept of 'pagination' or - breaking your form onto seperate pages. This can be a handy feature if you feel that your form is too ominous in it's entireity.</p>
<p>What we wanted to do however was build special logic into the sequencing of the pages. So based on how the user answers a question in RS Form, we direct them to the next question we want them to see. In the form builder world, this is sometimes refered to as branching logic. Understandably, the makers of RS Forms have not added this feature because it's possibly hard to administer. However by adding some jquery to the form, we can add the functionality we need.</p>
<p>Here's how you do it...</p>

<p> </p>
<p><strong>First you have to add the fields to your form. </strong></p>
<p>Here's a picture of how our form looks:</p>
<p><a class="jcepopup" target="_blank" title="rsform_components2" href="http://www.winworld.cc/images/blog/rsform_components2.png"><img alt="rsform_components2" src="http://www.winworld.cc/images/blog/thumbnails/thumb_rsform_components2.png" height="198" width="300" /></a></p>
<p>Take special note of your field names. You will need to manually reference every one of those names in your layout. We've built logic into our JavaScript to handle checkboxes, radios and pulldowns. These are the only fields you can use to affect logic that guides the form. You can add other fields but they'll just be used to store information.</p>
<p>Use RS Form's pagination to add your page breaks. Our JS uses them to control the form. You have to name then 1,2,3 etc as our form uses that to control everything. Don't forget to add a submit button on the final page.</p>
<p><strong>Next add your layout:</strong></p>
<p>It's helpful if you are 100% sure that you've got all your fields before you start customizing your layout. We've done a custom layout that uses a special design controlled by CSS. The different field elements are placed around the page.</p>
<p>Here's the layout for our sample form:</p>
<p>{codecitation class="brush:php" height="300px"}</p>
<p>{error}<br />&lt;div id="cost"&gt;<br /> &lt;table&gt;<br /> &lt;thead&gt;&lt;tr&gt;&lt;th colspan="3"&gt;Cost&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;<br /> &lt;tfoot&gt;<br /> &lt;tr class="footer"&gt;<br /> &lt;td&gt;Total Cost&lt;/td&gt;<br /> &lt;td colspan="2"&gt;&lt;span class="currency"&gt;$&lt;/span&gt;&lt;span class="value"&gt;0&lt;/span&gt;&lt;/td&gt;<br /> &lt;/tr&gt;<br /> &lt;/tfoot&gt;<br /> &lt;tbody&gt;<br /><br /> &lt;/tbody&gt;<br /> &lt;/table&gt;<br />&lt;/div&gt;<br />&lt;div class="formHeader"&gt;{global:formtitle}&lt;/div&gt;<br />&lt;div id="formWrapper"&gt;<br /> &lt;!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly --&gt;<br /> &lt;div id="rsform_7_page_0" class="questionParts"&gt;<br /> &lt;div class="paginator"&gt;<br /> &lt;div class="heading"&gt;Question 1 of X&lt;/div&gt;<br /> &lt;div class="nextPrev"&gt;{1:body}&lt;/div&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="questionWrapper"&gt;<br /> &lt;div class="question"&gt;{question1:caption} (*)&lt;/div&gt;<br /> &lt;div class="radioOptions"&gt;<br /> {question1:body}<br /> {question1:validation}<br /> &lt;/div&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="description"&gt;{question1:description}&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly --&gt;<br /> &lt;div id="rsform_7_page_1" class="questionParts"&gt;<br /> &lt;div class="paginator"&gt;<br /> &lt;div class="heading"&gt;Question 2 of X&lt;/div&gt;<br /> &lt;div class="nextPrev"&gt;{2:body}&lt;/div&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="questionWrapper"&gt;<br /> &lt;div class="question"&gt;{question2:caption} (*)&lt;/div&gt;<br /> &lt;div class="radioOptions"&gt;<br /> {question2:body}<br /> {question2:validation}<br /> &lt;/div&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="description"&gt;{question2:description}&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly --&gt;<br /> &lt;div id="rsform_7_page_2" class="questionParts"&gt;<br /> &lt;div class="paginator"&gt;<br /> &lt;div class="heading"&gt;Question 3 of X&lt;/div&gt;<br /> &lt;div class="nextPrev"&gt;{3:body}&lt;/div&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="questionWrapper"&gt;<br /> &lt;div class="question"&gt;{question3:caption}&lt;/div&gt;<br /> &lt;div class="radioOptions"&gt;<br /> {question3:body}<br /> {question3:validation}<br /> &lt;/div&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="description"&gt;{question3:description}&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly --&gt;<br /> &lt;div id="rsform_7_page_3" class="questionParts"&gt;<br /> &lt;div class="paginator"&gt;<br /> &lt;div class="heading"&gt;Question 4 of X&lt;/div&gt;<br /> &lt;div class="nextPrev"&gt;{4:body}&lt;/div&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="questionWrapper"&gt;<br /> &lt;div class="question"&gt;{question4:caption}&lt;/div&gt;<br /> &lt;div class="radioOptions"&gt;<br /> {question4:body}<br /> {question4:validation}&lt;/div&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="description"&gt;{question4:description}&lt;/div&gt;<br /> &lt;/div&gt;<br /> <br /> &lt;!-- Do not remove this ID, it is used to identify the page so that the pagination script can work correctly --&gt;<br /> &lt;div id="rsform_7_page_4" class="questionParts"&gt;<br /> &lt;div class="paginator"&gt;<br /> &lt;div class="heading"&gt;Conclusion&lt;/div&gt;<br /> &lt;div class="nextPrev"&gt;{submit:body}&lt;/div&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="questionWrapper"&gt;<br />{conclusion:body}<br />&lt;table&gt;<br />&lt;tr&gt;&lt;td&gt;<br />{Name:caption} * <br />&lt;/td&gt;&lt;td&gt;<br />{Name:body}<br />{Name:validation}<br />&lt;/td&gt;&lt;/tr&gt;<br />&lt;tr&gt;&lt;td&gt;<br />{Email:caption} * <br />&lt;/td&gt;&lt;td&gt;<br />{Email:body}<br />{Email:validation}<br />&lt;/td&gt;&lt;/tr&gt;<br />&lt;tr&gt;&lt;td&gt;<br />{Notes:caption}<br />&lt;/td&gt;&lt;td&gt;<br />{Notes:body}<br />{Notes:validation}<br />&lt;/td&gt;&lt;/tr&gt;<br />&lt;tr&gt;&lt;td&gt;<br />{Contact:caption}<br />&lt;/td&gt;&lt;td&gt;<br />{Contact:body}<br />{Contact:validation}<br />&lt;/td&gt;&lt;/tr&gt;<br />&lt;tr&gt;&lt;td&gt;<br />{Number:caption}<br />&lt;/td&gt;&lt;td&gt;<br />{Number:body}<br />{Number:validation}<br />&lt;/td&gt;&lt;/tr&gt;<br />&lt;tr&gt;&lt;td&gt;<br />{Company:caption}<br />&lt;/td&gt;&lt;td&gt;<br />{Company:body}<br />{Company:validation}<br />&lt;/td&gt;&lt;/tr&gt;<br />&lt;/table&gt;<br />{submit:body}<br /><br /> &lt;!--div class="question"&gt;{xxx:caption}&lt;/div&gt;<br /> &lt;div class="radioOptions"&gt;<br /> {xxx:body}<br /> {xxx:validation}&lt;/div--&gt;<br /> &lt;div class="clr"&gt;&lt;/div&gt;<br /> &lt;/div&gt;<br /> &lt;div class="description"&gt;{conclusion_info:body}&lt;/div&gt;<br /> &lt;/div&gt;<br /><br />{cost_table:body}<br />&lt;/div&gt;</p>
<p>{/codecitation}</p>
<p> </p>
<p>It's pretty obvious what is going on. The field names that you chose in the first step are reused in the layout. One thing to note especially however is <strong>rsform_7_page_4 </strong>you need to change the "7" to the ID of your actual form. Also note that the "4" is the name of the next paginator name.</p>
<p> </p>
<p><strong>Next put in your custom script</strong></p>
<p>The first thing you want to do is jump over to the css/JavaScript tab in RS Form and style your form. <strong>Please do not (NOT) use our styling. </strong>We're making this all available for free but we'd really appreciate it if you dream up your own quote layout.</p>
<p>{codecitation class="brush:css"}</p>
<p>&lt;link rel="stylesheet" rev="stylesheet" type="text/css" href="http://www.winworld.cc/jqueryui/jquery-ui-1.8.14.custom.css" /&gt;&lt;style type="text/css"&gt;<br /> #formWrapper {float:left; width:75%;margin-bottom:10px;}<br /> .questionParts {}<br /> .paginator {-webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #ECF0F3; margin-bottom:17px;}<br /> .paginator input {-webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #ECF0F3; background-color:white; color:#7793A9; font-weight:bold; text-transform:lowercase; font-family:Arial,sans; font-size:11px; padding:5px; margin:7px;}<br /> .paginator input:hover {border:1px solid #ECF0F3; background-color:#7793A9; color:white; cursor:pointer;}<br /> .paginator .heading {float:left; height:100%; background:url(/templates/winworld/images/right-triangle.png) no-repeat center right #F0F4F7; color:#7894A9; font-size:18px; padding: 10px 33px 10px 10px; font-weight:bold;}<br /> .questionWrapper {-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px; border:1px solid #ECF0F3; }<br /> .description {-webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #ECF0F3; border-top:none; padding:10px 17px; color:#7793A9; font-size:12px; text-indent:15px; background:url(/templates/winworld/images/info-icon.png) no-repeat 17px 10px;}<br /> .nextPrev {float:right;}<br /> .question {float:left; font-weight:bold;color:#506270;font-size:14px; padding:17px;}<br /> .radioOptions {float:right; padding:17px;}<br /> .checkboxOptions { clear:both; }<br /> .checkboxOptions input { clear:left; float:left; margin:3px 10px 3px 15px; }<br /> .checkboxOptions label { clear:right; display:block; line-height:17px; margin:0 15px 15px 0;}<br /> .formHeader {font-size:20px; color:#7894aa; font-family:District,DistrictDemi,Myriad Pro,Helvetica,Arial,sans;<br /> font-weight:bold; margin:40px 0 30px; padding: 0 0 0 40px; background:url(/templates/winworld/images/clip-board.png) no-repeat center left; float:left; clear:left;}<br /> span.pathway {display:none !important;}<br /> #cost {margin:30px 0 10px; -webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #bbc9d4; background-color:#e4e9ed; padding:3px; float:right;width:23%;}<br /> #cost table {-webkit-border-radius: 2px;-moz-border-radius: 2px;border-radius: 2px; border:1px solid #839eb1; border-collapse:collapse; width:100%;}<br /> #cost th {background-image:none; background-color:#92a9bb; color:white; padding:15px 20px; font-size:15px; text-align:left;}<br /> #cost td {padding:10px 0 10px 20px; color:#7994a9; font-size:9px; border-bottom:1px solid #e5eaee;<br /> background-color:white;}<br /> #cost .number {font-weight:bold;}<br /> #cost tr.footer td {background-color:#dde4ea; color:#92a9bb; padding:15px 20px; font-size:15px; font-weight:bold;}<br /> #cost td.x {padding-right:5px;}<br /> .radios label { clear: right; float: left; width: 90%;}<br /> .radios input { float:left; clear:left;}<br />&lt;/style&gt;</p>
<p>{/codecitation}</p>
<p>Note at the top there is an include for a CSS script. You'll need to put this folder in your web-root for that to work:<a class="jce_file" title="jqueryui.zip" href="http://www.winworld.cc/images/blog/jqueryui.zip"><img class="jce_icon" src="http://www.winworld.cc/plugins/editors/jce/tiny_mce/plugins/filemanager/img/ext/zip_small.gif" title="zip" style="border: 0px; vertical-align: middle;" />&nbsp;jqueryui.zip<span class=" jce_size">&nbsp;</span></a></p>
<p><strong>Next put in the actual JavaScript</strong></p>
<p>This is the trickiest part.<strong> </strong>You can't just copy and paste this part. Check out the code below:</p>
<p>{codecitation class="brush:javascript"}</p>
<p>&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"&gt;&lt;/script&gt;<br />&lt;script type="text/javascript" src="http://www.winworld.cc/jqueryui/jquery-ui-1.8.14.custom.min.js"&gt;&lt;/script&gt;<br />&lt;script type="text/javascript"&gt;<br /> jQuery.noConflict();<br /> (function($) {<br /> $(function() {<br /> var quest = "0",<br /> exclude = {},<br /> base_id = "#rsform_7_page_",<br /> cost;<br /> var questions ={<br /> 1:{<br /> type:"radio",<br /> options:{<br /> "yes":{<br /> cost:{},<br /> next:2<br /> },<br /> "no":{<br /> cost:{},<br /> next:3<br /> }<br /> }<br /> },<br /> 2:{<br /> type:"radio",<br /> options:{<br /> "Less than 50":{<br /> cost:{<br /> "Base":500,<br /> "Small Addon":1000,<br /> Option:"150/yr",<br /> Option2:"2/mo" <br /> },<br /> message:"It sounds like you said yes and then picked your options. That's great! Now on to the next question.",<br /> next:3<br /> },<br /> "More than 50":{<br /> cost:{<br /> "Big Version":3000,<br /> Option:"150/yr",<br /> Option2:"2/mo"<br /> },<br /> message:"You chose the larger option so we added more money to your estimate. Give us your money.",<br /> next:3<br /> }<br /> }<br /> },<br /> 3:{<br /> type:"checkboxes",<br /> options:{<br /> 'No':{<br /> cost:{},<br /> next:4<br /> },<br /> 'Yes':{<br /> cost:{<br /> "Base":500,<br /> "This Thing":500<br /> }<br /> },<br /> 'Yes and add pie':{<br /> cost:{<br /> "Pie":0<br /> }<br /> },<br /> 'Yes and add soda':{<br /> cost:{<br /> SSL:"150/yr",<br /> Soda:"2/mo"<br /> }<br /> }<br /> }<br /> },<br /> 4:{<br /> type:"select",<br /> options:{<br /> "none":{<br /> next:"end"<br /> },<br /> "1":{<br /> cost:{<br /> "Add One":150<br /> },<br /> next:"end"<br /> },<br /> "2":{<br /> cost:{<br /> "Add Two":300<br /> },<br /> next:"end"<br /> },<br /> "3":{<br /> cost:{<br /> "Add Three":450<br /> },<br /> next:"end"<br /> },<br /> "4":{<br /> cost:{<br /> "Add Four":600<br /> },<br /> next:"end"<br /> }<br /> }<br /> }<br /> };<br /> $('#formWrapper input[type="button"]').removeAttr("onclick");<br /><br /> //$('#formWrapper').append('&lt;textarea style="display:none;" name="form[cost_table]" id="cost-table"&gt;&lt;/textarea&gt;');<br /><br /> function handler(q,idx,i,next){<br /> if(idx) idx = parseInt(idx);<br /> if(idx &amp;&amp; i){<br /> exclude[idx] = [];<br /> if(q.options[i].next &amp;&amp; q.options[i].next!="end"){<br /> if(q.options[i].next &gt; idx+1){<br /> for(var l = idx+1;l&lt; q.options[i].next ;l++){<br /> exclude[idx].push(l);<br /> }<br /> }<br /> }<br /> }<br /> $('#cost tbody tr').remove();<br /> var total = 0;<br /> $('.questionParts').each(function(){<br /> var id = parseInt($(this).attr("id").split("_").pop())+1;<br /> if(questions[id]){<br /> var ok = true;<br /> for(var ex in exclude){<br /> if($.inArray(id,exclude[ex])&gt;-1){<br /> ok = false;<br /> break;<br /> }<br /> }<br /> if(ok){<br /> var q = questions[id];<br /> if(q.type=="radio"){<br /> var opt = $.trim($(this).find('input[type="radio"]:checked').val());<br /> if(q.options[opt]){<br /> if(q.options[opt].cost){<br /> for(var j in q.options[opt].cost){<br /> var add = true;<br /> $("#cost tbody .name").each(function(){<br /> if($(this).html()==j){<br /> add = false;<br /> }<br /> })<br /> if(add){<br /> total += parseFloat(q.options[opt].cost[j]);<br /> $("#cost tbody").append('&lt;tr&gt;'+<br /> '&lt;td class="name"&gt;'+j+'&lt;/td&gt;'+<br /> '&lt;td class="number"&gt;&lt;span class="currency"&gt;$&lt;/span&gt;&lt;span class="value"&gt;'+q.options[opt].cost[j]+'&lt;/span&gt;&lt;/td&gt;&lt;td class="x"&gt;&lt;/td&gt;'+<br /> '&lt;/tr&gt;');}<br /> }<br /> }<br /> }<br /> }else if(q.type=="select"){<br /> var opt = $.trim($(this).find('select').val());<br /> if(q.options[opt]){<br /> if(q.options[opt].cost){<br /> for(var j in q.options[opt].cost){<br /> var add = true;<br /> $("#cost tbody .name").each(function(){<br /> if($(this).html()==j){<br /> add = false;<br /> }<br /> })<br /> if(add){<br /> total += parseFloat(q.options[opt].cost[j]);<br /> $("#cost tbody").append('&lt;tr&gt;'+<br /> '&lt;td class="name"&gt;'+j+'&lt;/td&gt;'+<br /> '&lt;td class="number"&gt;&lt;span class="currency"&gt;$&lt;/span&gt;&lt;span class="value"&gt;'+q.options[opt].cost[j]+'&lt;/span&gt;&lt;/td&gt;&lt;td class="x"&gt;&lt;/td&gt;'+<br /> '&lt;/tr&gt;');}<br /> }<br /> }<br /> }<br /> }else if(q.type=="checkboxes"){<br /> $(this).find('input[type="checkbox"]:checked').each(function(){<br /> var opt = $.trim($(this).val());<br /> if(q.options[opt]){<br /> if(q.options[opt].cost){<br /> for(var j in q.options[opt].cost){<br /> var add = true;<br /> $("#cost tbody .name").each(function(){<br /> if($(this).html()==j){<br /> add = false;<br /> }<br /> })<br /> if(add){<br /> total += parseFloat(q.options[opt].cost[j]);<br /> $("#cost tbody").append('&lt;tr&gt;'+<br /> '&lt;td class="name"&gt;'+j+'&lt;/td&gt;'+<br /> '&lt;td class="number"&gt;&lt;span class="currency"&gt;$&lt;/span&gt;&lt;span class="value"&gt;'+q.options[opt].cost[j]+'&lt;/span&gt;&lt;/td&gt;&lt;td class="x"&gt;&lt;/td&gt;'+<br /> '&lt;/tr&gt;');}<br /> }<br /> }<br /> }<br /> });<br /> }<br /> }<br /> }<br /> });<br /> $("#cost tfoot .value").html(total);<br /> $('#cost_table').val($("#cost").html());<br /> if(idx &amp;&amp; i){<br /> if(q.options[i].next &amp;&amp; q.options[i].next!="end"){<br /> questions[q.options[i].next].prev = idx;<br /> }else if(q.options[i].next!="end"){<br /> questions[idx+1].prev = idx;<br /> }<br /> }else{<br /> if(idx) questions[idx+1].prev = idx;<br /> }<br /> if(next){<br /> if(i){<br /> $(".questionParts").hide();<br /> if(q.options[i].next!="end"){<br /> $(base_id+(q.options[i].next-1)).show();<br /> }else{<br /> $(base_id+(idx)).show();<br /> }<br /> }else if(idx){<br /> $(".questionParts").hide();<br /> $(base_id+(idx)).show();<br /> }<br /> }<br /> }<br /><br /> $.each(questions, function(idx, q) {<br /> if(q.type==="radio"){<br /> $(base_id+(idx-1)+" input[type='radio']").click(function(){<br /> var $this = $(this);<br /> var i;<br /> for(i in q.options){<br /> if($.trim(i).toLowerCase()==$.trim($this.val()).toLowerCase()){<br /> break;<br /> }<br /> }<br /> if(q.options[i].message){<br /> $('&lt;div id="info'+idx+'" title="Info"&gt;'+q.options[i].message+'&lt;/div&gt;').dialog({<br /> modal:true,<br /> resizable:false,<br /> buttons:{<br /> Ok:function(){<br /> handler(q,idx,i,true);<br /> $(this).dialog("close");<br /> }<br /> },<br /> close:function(){<br /> $(this).dialog("destroy").remove();<br /> }<br /> });<br /> }else{<br /> handler(q,idx,i,true);<br /> }<br /><br /> })<br /> }else if(q.type==="select"){<br /> $(base_id+(idx-1)+" select").change(function(){<br /> var i;<br /> for(i in q.options){<br /> if($.trim(i).toLowerCase()==$.trim($(this).val()).toLowerCase()){<br /> break;<br /> }<br /> }<br /> if(q.options[i].message){<br /> $('&lt;div id="info'+idx+'" title="Info"&gt;'+q.options[i].message+'&lt;/div&gt;').dialog({<br /> modal:true,<br /> resizable:false,<br /> buttons:{<br /> Ok:function(){<br /> handler(q,idx,i,true);<br /> $(this).dialog("close");<br /> }<br /> },<br /> close:function(){<br /> $(this).dialog("destroy").remove();<br /> }<br /> });<br /> }else{<br /> handler(q,idx,i,true);<br /> }<br /> })<br /> }else if(q.type==="checkboxes"){<br /> $(base_id+(idx-1)+" input[type='checkbox']").click(function(){<br /> handler(q,idx);<br /> })<br /> }<br /> });<br /><br /> $('.nextPrev').click(function(e){<br /> var $target = $(e.target);<br /> if($target.is('input[value="Next"]')){<br /> var id = $target.attr("id").split("Next")[0];<br /> var question = questions[id];<br /> if(question.type=="radio"){<br /> var val = $.trim($(base_id+(id-1)+" input:checked").val()).toLowerCase();<br /> if(val!==null &amp;&amp; val!==undefined &amp;&amp; val!=""){<br /> handler(questions.id,id,null,true);<br /> }<br /> }else if(question.type=="checkboxes"){<br /> handler(questions.id,id,null,true);<br /> }else if(question.type=="select"){<br /> var val = $.trim($(base_id+(id-1)+" select").val()).toLowerCase();<br /> if(val!==null &amp;&amp; val!==undefined &amp;&amp; val!=""){<br /> handler(questions.id,id,null,true);<br /> }<br /> }<br /> }else if($target.is('input[value="Prev"]')){<br /> var id = parseInt($target.parents(".questionParts:first").attr("id").split("_").pop())+1;<br /> if(questions[id]){<br /> $(".questionParts").hide();<br /> $(base_id+(questions[id].prev-1)).show();<br /> }<br /> }<br /> })<br /> });<br /> })(jQuery);<br />&lt;/script&gt;</p>
<p>{/codecitation}</p>
<p>Again, note the include at the beginning, you'll want to put the above Zip folder in your webroot.</p>
<p>Here's how the script works. You have to make a perfect JSON object. Its a variable that holds the instructions for the whole form.</p>
<p>At the beginning, be sure to set your base_id. Be sure to use your actual RS Form ID.</p>
<p>Bracket 1 corresponds to the page prior to pagebreak 1.</p>
<p>Type can be radio, checkboxes or select.</p>
<p>Options indicate what happen if a choice is made.</p>
<p>Cost allows you to add things to the cost table.</p>
<p>Cost items with spaces in the name need to be put in quotes.</p>
<p>Prices with non-numerics need to be put in quotes.</p>
<p>If you add the same item twice it will not add it to the cost table twice.</p>
<p>Next designates what the next question is based on if they chose the given answer.</p>
<p>If this form implementation does not work for you, it is probably because of a misformatted JSON object. Be very aware of quotes and commas. You need a comma after repeating elements - all but the last. See the example.</p>
<p><strong>Final Step: Set emails and thankyou messages</strong></p>
<p>The rest of the steps for setting up a branching logic tree form in RS Form are the same as normal form setups. Don't forget to set your thankyou page text, your user and admin emails. Be sure to test a lot and do your own custom styling. This type of form setup can take some hours but once you have it in place, this framework is versitile because it lets you easily change things.</p>
<p>For those of you who have a recent version of RS Form, I have loaded an export of an example form in the following zip. If you don't have the same version, this import won't work however. Try and understand how everything is working so you can really get the most out of this form.</p>
<p>Download here: <a class="jce_file" title="rsform_instant_quote.zip" href="http://www.winworld.cc/images/blog/rsform_instant_quote.zip"><img class="jce_icon" src="http://www.winworld.cc/plugins/editors/jce/tiny_mce/plugins/filemanager/img/ext/zip_small.gif" title="zip" style="border: 0px; vertical-align: middle;" />&nbsp;rsform_instant_quote.zip</a></p>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Fri, 26 Aug 2011 20:35:56 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/25-joomla/257-creating-branching-logic-in-multi-page-rs-form-pro.html</guid>
        </item>
        <item>
            <title>Processing Credit Card Payments with RS Form Pro</title>
            <link>http://www.winworld.cc/blog/25-joomla/256-processing-credit-card-payments-with-rs-form-pro.html</link>
            <description><![CDATA[<p>RS Forms is a great component. It lets you build forms on your website by adding the fields you want. There are a number of default layouts for the form but what I like is that you can do your own layout for the form by moving {tags} around in HTML and putting the fields where you want them. you can also add attributes to fields for JavaScript actions and CSS styling. This is the first of two new tutorials I'm doing for RS Form. I have done&nbsp; previous tutorials that you can find <a href="http://www.winworld.cc/index.php?option=com_content&amp;view=category&amp;id=19&amp;Itemid=98&amp;filter=RS+Form">here</a>. .</p>
<h2>How to setup RS Forms Pro for Authorize.net payments</h2>
<p><strong>1. SSL in place</strong></p>
<p>The first thing you have to do is get yourself an SSL certificate and make sure that is configured. Then you have to make sure that when you send people to the form, that the link is HTTPS. It is possible to PHP code in the form to sense this and automatically redirect but we have not bothered with this.</p>

<p><strong>2. Build the form</strong></p>
<p>You need to create your form and add at least the minimum required billing fields. You can ask for much more information however. Your minimum fields should be:</p>
<ul>
<li>First Name</li>
<li>Last Name</li>
<li>Amount</li>
<li>Card Type (pull down) </li>
<li>Expiration (text, tell them to enter mm/yy format)</li>
<li>Credit Card Number</li>
<li>Billing steet</li>
<li>City</li>
<li>State</li>
<li>Zip</li>
</ul>
<p><a rel="lightbox[]" target="_blank" title="rsform_components" href="http://www.winworld.cc/images/blog/rsform_components.png"><img alt="rsform_components" src="http://www.winworld.cc/images/blog/thumbnails/thumb_rsform_components.png" height="280" width="300" /></a></p>
<p>You may also want to ask for their email address, phone number, company name etc.Take note of what you NAME each field as you'll need to incorporate the field names into the credit card processing script.</p>
<p><strong>3. Add the credit card processing scripts</strong></p>
<p>In RS Form, go to the tab called "scripts".</p>
<p>To the "Script called on form display" add:</p>
{codecitation style="brush: php;"} 
if(isset($_SESSION['failed_transaction']) && isset($_SESSION['failed_transaction_count'])  && $_SESSION['failed_transaction_count'] == 0){
echo '<div style="color:red;font-size: 14px;font-weight: bold; padding:5px;">'.$_SESSION['failed_transaction'].'</div>';
$_SESSION['failed_transaction_count'] = $_SESSION['failed_transaction_count'] +1;
}
 {/codecitation}
<p>This is the script that will check to see if the form has already been submitted and if it's being returned with a credit card processing error. If so this script assumes an attempt has already been made and shows the error to the user.</p>
<p> </p>
<hr />
To the "Script called on form process" add: {codecitation style="brush: php;"} 
if(!empty($_POST['form']['ccnum']) && !empty($_POST['form']['ccexp']) && !empty($_POST['form']['amount']) && !empty($_POST['form']['fname']) && !empty($_POST['form']['lname']) && !empty($_POST['form']['address']) && !empty($_POST['form']['state']) &&  !empty($_POST['form']['zip'])){

$post_url = "https://secure.authorize.net/gateway/transact.dll";
$post_values = array(
	
	// the API Login ID and Transaction Key must be replaced with 
        //valid values

	"x_login"		=> "YOURVALUEHERE",
	"x_tran_key"		=> "YOURVALUEHERE",

	"x_version"		=> "3.1",
	"x_delim_data"		=> "TRUE",
	"x_delim_char"		=> "|",
	"x_relay_response"	=> "FALSE",

	"x_type"		=> "AUTH_CAPTURE",
	"x_method"		=> "CC",
	"x_card_num"		=> $_POST['form']['ccnum'],
	"x_exp_date"		=> $_POST['form']['ccexp'],

	"x_amount"		=> str_replace( array('$',',') ,
                                   '' , $_POST['form']['amount']),
	"x_description"		=> "Inv num:".$_POST['form']['invoicenum'],

	"x_first_name"		=> $_POST['form']['fname'],
	"x_last_name"		=> $_POST['form']['lname'],
	"x_address"		=> $_POST['form']['address'],
	"x_state"		=> $_POST['form']['state'],
	"x_zip"			=> $_POST['form']['zip']
	
);
$post_string = "";
foreach( $post_values as $key => $value )
	{ $post_string .= "$key=" . urlencode( $value ) . "&"; }
$post_string = rtrim( $post_string, "& " );

$request = curl_init($post_url); // initiate curl object curl_setopt($request, CURLOPT_HEADER, 0); /
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($request, CURLOPT_POSTFIELDS, $post_string); 
curl_setopt($request, CURLOPT_SSL_VERIFYPEER, FALSE); 
$post_response = curl_exec($request); 
curl_close ($request); // close curl object


$response_array = explode($post_values["x_delim_char"],$post_response);


/*echo "<OL>\n";
foreach ($response_array as $value)
{
	echo "<LI>" . $value . " </LI>\n";
	$i++;
}
echo "</OL>\n";*/

}else{
echo'<script type="text/javascript"> alert("Please fill in mandatory fields!");
</script>';
}
 {/codecitation}
<p>This script does all the heavy lifting. You have to edit this script a lot. Every where it says $_POST['form']['whatever'] - you have to change it to what you used for that actual field when you built the form. So if you NAMED your "amount" field "amt" then you should put that in the code.Pay attention to the part at the beginning, it is checking for your required fields. You need to set those to what your required fields actually are.</p>
<p> </p>
<hr />
To the "Script called after form has been processed" add: {codecitation style="brush: php;"}
if($response_array[0] != '1'){
$error = $response_array[3];
$msg = str_replace('(TESTMODE)','',$error);
jimport( 'joomla.application.component.controller' );
 global $mainframe;
if(isset($_SESSION['failed_transaction'])) unset($_SESSION['failed_transaction']);
if(isset($_SESSION['failed_transaction_count'])) unset($_SESSION['failed_transaction_count']);

$_SESSION['failed_transaction_count'] =0;
$_SESSION['failed_transaction'] = 'Transaction failed! Error: '.$msg;
$redirecturl = JRoute::_('index.php?option=com_rsform&formId=5&Itemid=99999');
$mainframe -> redirect($redirecturl,'error');
return;
}else{
//lets wipe ANY ccnum that hasn't been wiped! 
$db =& JFactory::getDBO();
$query = "update `jos_rsform_submission_values` set `FieldValue` = concat('****-****-****-',substr(`FieldValue`,13)) where `FieldName` = 'ccnum' and `FieldValue` NOT LIKE '%****%' ";
$db->setQuery($query);
$result = $db->query();
}
 {/codecitation}
<p>This is the post processing script. If the card ran successfully it allows the form data to save to the database. If it did not it will redirect to reload the form with the credit card error message so the user can try again.</p>
<p>You need to especially note where it says "formId=X" this is where you set what your formId is or else it will not redirect back to the correct form. At the end of the script it wipes the CC number so you're not saving it in your database. Look at where it says where 'FieldName' = '??' you have to change it to what you called your credit card number field. Its important to do this step. It will wipe all field submissions from all forms with that feild name.</p>
<p><strong>4. Test and tweak</strong></p>
<p>Don't forget to edit your user and admin emails. You have to manually include the fields in the email that you want to send. I've provided instructions here to build this form from scratch but if you want to take a shot at just installing my backup version into your RS Form, I've provided the file here. Be warned however, if your version of RS Form does not match, this may not work.</p>
<p><a class="jce_file" title="rsform_authorize_payment.zip" href="http://www.winworld.cc/images/blog/rsform_authorize_payment.zip"><img class="jce_icon" src="http://www.winworld.cc/plugins/editors/jce/tiny_mce/plugins/filemanager/img/ext/zip_small.gif" title="zip" style="border: 0px; vertical-align: middle;" />&nbsp;rsform_authorize_payment.zip<span class=" jce_size">&nbsp;</span></a></p>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Fri, 26 Aug 2011 19:20:23 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/25-joomla/256-processing-credit-card-payments-with-rs-form-pro.html</guid>
        </item>
        <item>
            <title>How to compare us to other web firms: what's not included</title>
            <link>http://www.winworld.cc/blog/17-blog/253-how-to-compare-us-to-other-web-firms-whats-not-included.html</link>
            <description><![CDATA[<p><img style="margin-right: 20px; margin-bottom: 15px; float: left;" alt="focus" src="http://www.winworld.cc/images/blog/focus.jpg" height="167" width="250" />When shopping for a new web provider, it can be difficult to compare apples to apples. There are so many variables. One of the main points of comparison is price. With web development however there could be so many things included or not included.</p>
<p>Take house building for example, will the builder also landscape your yard? Will they also furnish and decorate the new house?</p>
<p>With websites, there are services that some firms throw into the package deal that we feel should be priced seperately (analogous to the house example in landscapers and interior decorators).</p>

<h4>Search Engine Optimization (SEO)</h4>
<p>Some web comanies claim that their websites will have SEO included. What we say is our websites have all the structure and tools for SEO.</p>
<p>To say that SEO is included is similar to saying that purchasing a new business with no track record is guaranteed to meet 100% of it's sales goals.</p>
<p>If you're comparing two web proposals and the one has SEO included costs $5000 more, then the SEO may really be included as more time will be available to work on optimization after the site is launched. It's one thing to make a claim that SEO is included but you have to evaluate what that really means.</p>
<p>In a prior article we expalin that real <a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=252:how-not-to-get-scammed-on-seo&amp;catid=17&amp;Itemid=26">SEO takes a lot of time and money</a> and is comprable to the time and effort it takes to build a solid reputation in business. Although we write a lot about it and we know a lot about it, we know that to do it well, we'd really have to devout ourselves exclusively to SEO full time.</p>
<p>When you see SEO thrown in as a cheap part of a web package, really question whether that component will acheive anything at all. Be an educated consumer and <a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=252:how-not-to-get-scammed-on-seo&amp;catid=17&amp;Itemid=26">read more about this topic</a>.</p>
<h4>Content writing</h4>
<p>Some web firms are really more marketing agencies than they are web design companies. The way to recognize this is to look at their packages, or their proposal. If their focus is on writing content for you, they may only place a minor emphasis on the actual website itself. It may not even be discussed in the proposal what system you're getting for a content management system or what type of design you'll get. They may <a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=251:comparing-us-to-other-web-firms-templates&amp;catid=17&amp;Itemid=26">pull a free template</a>, but their focus is on the written letter. We're not saying that is wrong, it's just a different approach. WinWorld is definately a web design company. We do custom web designs, we're experts in the web management systems we provide. We leave writing about your business, up to you. You are the expert in your business, you know what you want to say.</p>
<p>If you need help getting it out, you can bullet out the points of what you want to say and use a content writer. We can refer you to some great content writers.</p>
<p>We'll do as much as we can to help you evaluate apples to apples in regards to what is included in our web packages and what is not. Be sure you have all the information before you buy.</p>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Tue, 16 Aug 2011 19:22:42 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/17-blog/253-how-to-compare-us-to-other-web-firms-whats-not-included.html</guid>
        </item>
        <item>
            <title>How not to get scammed on SEO</title>
            <link>http://www.winworld.cc/blog/23-search-engine-optimization/252-how-not-to-get-scammed-on-seo.html</link>
            <description><![CDATA[<h3><a rel="lightbox[]" target="_blank" title="brooklyn_bridge_for_sale" href="http://www.winworld.cc/images/blog/brooklyn_bridge_for_sale.jpg"><img style="margin-right: 20px; margin-bottom: 15px;" alt="brooklyn_bridge_for_sale" src="http://www.winworld.cc/images/blog/brooklyn_bridge_for_sale.jpg" align="left" height="182" width="250" /></a>What is SEO?</h3>
<p>SEO stands for Search Engine Optimization. It's the practice of doing things to and around your website that optimizes it to rank higher in search engine results. Many people are aware of SEO but knowing that it has something to do with tags is about the extent of their knowledge.</p>
<p>The purpose of this article is to help you undrestand how not to get burned by companies who are promising a great deal in the arena of SEO for for maybe only a few hundred dollars.</p>
<h3>A true story</h3>
<p>I was speaking with a client recently. He had asked us about SEO and we'd referred him to our <a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=209:christmas-2010-newsletter&amp;catid=18&amp;Itemid=95">number one provider</a> who we always refer people to for SEO. The gentleman contacted our SEO referal but was discouraged by the truth. He was told that it would take months to build up a first page ranking in a primary search phrase and was also told that the effort would equate to $2-3,000.</p>

<p>So like any good consumer, our client shopped around. In the world of SEO there is a large quantity of companies promising immediate, first page results, for only a few hundred dollars. Most of these companies have compelling marketing and can even produce examples of high rankings they've achived. Our client engaged with one particular company for $650. The company promised a first page ranking in at least three designated phrases in 1-2 months. Our client paid for the service and was told by the SEO provider that they would be logging directly into his website to make adjustments. Our client give the SEO provider our contact information so that we could help them get logged in. The SEO company never contacted us to gain access to the website and never logged in or made any changes. 2-3 months later our client followed up. The SEO company swore that they'd completed their work.</p>
<p>The only other explanation that I could come up with was that perhaps the SEO company had "built some links" to point into our client's website. I did a "backlink search" and found no new links. The evidence seemed to point pretty clearly to the fact that our client had been completely ripped off. It would have been better if our client had put that money in the shredder:</p>
<h3>Like night and day, an SEO service that actually provides results!</h3>
<p>Compare the above story to an experience that we had recently. We know a lot about SEO. We blog about it frequently. We've researched dozens of SEO firms in order to provide good referals to our clients. We've even spent money on different firms in order to really test out their services. Recently we engaged the SEO company <a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=209:christmas-2010-newsletter&amp;catid=18&amp;Itemid=95">that I mentioned before</a>. Working with our primary contact there was very different to experiences we'd had before. The one thing that really stood out was that he took a lot of time on us. He took time to understand what we were trying to achieve. We designated one phrase we wanted to rank with and one page on our website we wanted to come up for that phrase. He went back and forth with us almost a dozen times suggesting changes to this one page. His work on this one page spanned months of time. He'd always check where we were at and follow up with us. We were busy but he was very fastedious about following up with us and pushing us to move forward with the project. He didn't just leave it on us. He even went beyond the optimization of content and advised us the design of the page. He truly wanted our page to look good and to convert visitors to that page into customers. Finally after some time, we reached a first place ranking.</p>
<p>I was very happy with the experience of this SEO service and I was convinced that it was time and attentiveness that made the difference where other SEO services had failed before.</p>
<h3>Being an educated consumer helps you not get scammed</h3>
<p>The first way to help yourself is to learn some SEO basics. It may only take you about 20-30 minutes of reading but it could save you 100s if not 1000s of dollars.</p>
<p>For example, most people don't know that SEO is split into two main components optimizing content (e.g. tagging) and generating backlinks.</p>
<h4>"Adding tags"</h4>
<p>I find that the majority of people only know about the first aspect, yet most professional SEOs will tell you that optimizing internal content only constitutes the minority of the weight that search engines place on search engine ranking. The majority of emphasis is placed on backlinks, or links pointing back to your website.</p>
<p>In an article called, <a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=77:dem-tag-thingies&amp;catid=23&amp;Itemid=26">debunking the tag myth</a>, I explain that companies who are just going to optimize your content and add tags, may not achieve any results for you.</p>
<h4>Backlinks</h4>
<p>You may be wasting time and money with them. In another article called "<a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=122:a-backlink-is-worth-a-1000-words&amp;catid=23&amp;Itemid=26">a backlink is worth a 1000 words</a>" I further explain that Google models it's search results very similarly to the way humans guage "word of mouth" to evaluate the credability of a business. In essense, the more backlinks you have from <strong>reputable </strong>websites, the more buzz Google sees about your business on the web, which increases your ranking.</p>
<h4>We'll submit your site to 20 search engines and get you 1000 links!</h4>
<p>There are firms (mostly overseas in places like India) that will sell you a one-time SEO solution. The claim above is similar to claims they make. First of all, there are only a few major search engines. The one with the largest market share is Google. The concept of "submitting a site" is pretty foolhardy because the way Google finds websites is by crawling the internet. If it knows of a website and crawls it, and finds that it's linking to your site, that is how it discovers your site. It does that quickly. When we post content on winworld.com, sometimes its available on Google within a couple of hours because they crawl our site frequently. Google has immense power of discovering new information on the web.</p>
<p>Please do not buy 1000 links. This will hurt you so much you may never be able to recover your ranking. What these companies do is submit your link to any website out there. Often times the SEO company themselves owns the website and manages it as a large "link farm." Google knows about these sites and having your link on these sites will actually demote you. We've even had clients who've used these services have their site completely black listed because these link farms sometimes contain viruses and you can be blackend by sheer associate.</p>
<h3>How it really works - it's like the real world</h3>
<p>Please understand that SEO is not some get rich quick scam you can pull. Get rich quick schemes may have short term gains but they have a long term loss when people figure them out. If you started a business in a city and scammed people for their money, you might gain in the short term but you'd go out of business pretty quickly.</p>
<p>SEO is like the real world. To start a business in a comunity you have to work at it. You have to provide a quality product and service and generate word of mouth. On the web you have to have a quality website, you have to add to it regular with resources that are truly helpful, slowly you will become more well known and will start to get more inbound links coming to your website.</p>
<p>Again, Google's algorithms are based on human behavior. If we as a people have methods that help us to evaluate businesses and Google's main value proposition is to return quality recommendations to us, Google will try to be as human in it's evaluation as possible. What this means is that if there is any trick in the book to gain false or rapid rankings, Google is going to try and rule that out.</p>
<p>A real SEO can work with you to help you gain traction in your ranking but know that it will take time and consequently, will cost more than $100. Expecting the world and only paying $100 is like opening a store on a back street and being surprised that you're not flooded with customers the moment you first open your doors.</p>
<p>To read more about SEO, click the following link to be take to the SEO section on our blog: <a class="orangebutton_sm" href="http://www.winworld.cc/index.php?option=com_content&amp;view=category&amp;id=23:search-engine-optimization&amp;layout=blog&amp;Itemid=26"><span>More SEO articles</span></a></p>
<p> </p>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Tue, 16 Aug 2011 18:09:25 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/23-search-engine-optimization/252-how-not-to-get-scammed-on-seo.html</guid>
        </item>
        <item>
            <title>Understanding web templates</title>
            <link>http://www.winworld.cc/blog/17-blog/251-comparing-us-to-other-web-firms-templates.html</link>
            <description><![CDATA[<h5><img style="margin-right: 20px; margin-bottom: 15px; float: left;" alt="jigsaw-cookie-cutter1" src="http://www.winworld.cc/images/blog/jigsaw-cookie-cutter1.jpg" height="153" width="250" />What is a template?</h5>
<p>A template is a design someone has already put together that can be used for a website. It may be a generic all-purpose design or it may be an industry specific design, such as for restaurants or churches.</p>
<p>A good example is a Power Point template, have you ever gone to a conference and see two people use the same design theme on their powerpoint? Not really a huge deal but they did look the same. Another example is showing up to an event wearing the same dress as someone else. That is embarassing.</p>
<p>It's not that templates look bad, some look great. We've actually <a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=201:the-cheapest-website-obtainable-on-the-internet-today&amp;catid=17&amp;Itemid=26">written posts</a> on this blog before saying that if you're budget is very limited, at least get a good looking template and get started with that.</p>

<p>One aspect about a template is that it's reusable so many people might use the same one. Examples of templates include Joomla or WordPress templates. Joomla and WordPress are two popular open source "content management systems." They are web based systems that let you add to or edit your web pages. There are galleries out there that provide 100s of free designs that you can install into one of these systems.</p>
<h5>A template should cost less</h5>
<p>The reason for this article is to bring attention to the fact that <strong>a template design should cost less</strong>. Pricing on website design is fairly readily available throughout the internet, but as you evaluate pricing, you need to be very careful and very aware if you're buying a template or a <a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=250:comparing-us-to-other-web-firms-design&amp;catid=17&amp;Itemid=26">custom design</a>. What we're seeing is that many web developers are selling packages that include template designs but they're setting the price for those packages such that <strong>you could get a custom design elsewhere for the same price</strong>.</p>
<p>Don't missunderstand, we're not saying that it is wrong to provide templates. We're not even saying it's wrong to charge for a free template. There is setup work involved, there is customization involved. It can be a great way to get a website up and running quickly. We are saying that templates should cost less and custom designs should cost more. If a custom design costs $5 then a consumer should beware that a template should not also cost $5.</p>
<p>So if you're shopping for web design and it's unclear whether you're getting a template or a custom design, please ask and work that into your evaluation.</p>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Tue, 16 Aug 2011 17:42:55 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/17-blog/251-comparing-us-to-other-web-firms-templates.html</guid>
        </item>
        <item>
            <title>Comparing us to other web firms: design</title>
            <link>http://www.winworld.cc/blog/17-blog/250-comparing-us-to-other-web-firms-design.html</link>
            <description><![CDATA[<p><img style="margin-right: 20px; margin-bottom: 15px; float: left;" alt="polls_apples_oranges_3217_631564_poll_xlarge" src="http://www.winworld.cc/images/blog/polls_apples_oranges_3217_631564_poll_xlarge.jpeg" height="252" width="252" />When you're purchasing a web site from a design company, there are a number of comparisons you can make, such as:</p>
<ul>
<li>Price</li>
<li>Are they local?&nbsp;</li>
<li>Are they big/old enough to indicate they'll be able to support you tomorrow?</li>
<li>What system do they base the website on? </li>
<li>Design</li>
</ul>
<h5>Both clients and web companies vary in design perceptivity</h5>
<p><strong>Clients: </strong>Over the years I've come to learn that design is very subjective. The way I know this is sometimes a client who is designing a site with us will give us an example of something that they like. I look at it and I have to ask "are you kidding?" I don't want to point any specific examples out, but they might look like the ones found <a href="http://www.topdesignmag.com/20-examples-of-bad-web-design/">here</a>.</p>
<p><strong>Designers: </strong>Flip the perspective - some web developers also are not very design concious. It's just a matter of how the brain is wired. Some web developers have engineering backgrounds. They enjoy the technical and functional aspects of web development, but they may be the first to tell you that their design sense is ver limited. They will deliver a functional and clean website but it may be just plain.</p>

<h5>Design is important</h5>
<p>I was speaking with someone recently about designing packaging for informational material. I shared with them that they should budget at least $1000 (but probably more) to have their product packaging designed. They were incredulous. My point was that if the product sells for $15-20 each and you sell 1000 - isn't that a good investment? Or look at it this way, if 5000 people are evaluating the product and all they see is the cover, don't you want more people than less to buy? The packaging is all they have to go on to make their decision.</p>
<p>Websites can get 100s or 1000s of visitors over time. Prospects who are quickly scanning what is available in order to make their decision. They make this decision based on what they see and their perception of it.</p>
<h5>How to compare us</h5>
<p>It's really simple. Pull up our portfolio and pull up theirs. Here's an example of one of our designs vs. a design found on NetworkSolutions.com:</p>
<table class="portfolio" border="0">
<tbody>
<tr>
<td><img alt="cornbread-lrg" src="http://www.winworld.cc/images/blog/cornbread-lrg.jpg" height="213" width="320" /></td>
<td><img alt="dd-sample-webdesign-05" src="http://www.winworld.cc/images/blog/dd-sample-webdesign-05.gif" height="207" width="320" /></td>
</tr>
<tr>
<td><a href="http://www.winworld.cc/index.php?option=com_content&amp;view=article&amp;id=25&amp;Itemid=54">Food related website</a> by WinWorld</td>
<td>Food related website by NS</td>
</tr>
</tbody>
</table>
<p> </p>
<p>The one on the left has a lot of detailed elements whereas the one on the right is what you'd call an "L-frame" - pretty flat. No one at WinWorld would ever say that we're the only company in the world to do good design. We're priviledged to have many talented professionals in our industry. We would however be confident that we offer incredible value when it comes to design.&nbsp;</p>
<h5>What about cost?</h5>
<p>In the above example, a client would neccessarily be paying more or less for either design. But what if you do find a cheaper option. Lets say you're starting out and you only have a lesser budget. My recommendation would be two-fold.</p>
<p>a) It's better to have somethig than nothing. If your budget is fixed then you're obviously only going to select a solution in your range.</p>
<p>b) Consider spending more</p>
<p>I went to the website of a food vendor in town recently. They did not have a logo and they had a free website that didn't look that great. On one hand I appreciated that they'd put any info up at all, but on the other hand... it made me feel like they didn't believe in their offering. As if to say that they didn't think it's going to be a big enough hit to cover an extra few $100 on marketing expense.</p>
<p><strong>Good design projects confidence</strong>. A book seller will drop $1000s on a cover knowing they'll sell 1000s of copies. Of course it's arguable which comes first, the design or the profits, but I'll leave that to you to decide.</p>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Tue, 16 Aug 2011 16:59:43 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/17-blog/250-comparing-us-to-other-web-firms-design.html</guid>
        </item>
        <item>
            <title>Automatic Podcast to YouTube Converter</title>
            <link>http://www.winworld.cc/blog/17-blog/249-converting-podcast-to-youtube.html</link>
            <description><![CDATA[<p><img style="margin-right: 20px; margin-bottom: 15px; float: left;" alt="podcast2youtube_copy" src="http://www.winworld.cc/images/blog/podcast2youtube_copy.jpg" height="300" width="300" />Anyone who has developed a podcast knows that it is a pretty easy thing to do. I think that is one of the reasons why the whole idea of podcasting spread so quickly. You can host your mp3 audios or your mp4 videos anywhere. All you have to do to offer your audio or videos in podcast format is to maintain a "feed" file that tells a podcast reader where to find the latest media files. Usually that podcast reader is iTunes. When you subscribe to a podcast, your iTunes will periodically check that feed to see if any new media has been added lately. So as an author of podcast all you have to do is a) upload your file somewhere b) update the podcast file. The format for the file is fairly simple.&nbsp; You just keep adding new episodes to the top in between &lt;item&gt; tags. You put the title between &lt;title&gt; tags and so on. The full podcast format is explained here: <a href="http://www.apple.com/itunes/podcasts/specs.html#example">http://www.apple.com/itunes/podcasts/specs.html#example</a></p>
<p>There are programs that generate the file for you. There are also plenty of websites that let you simply upload your files and type in your titles and then they generate the feed for you.</p>
<p>As easy as a podcast is to set up, there are still people out there who don't understand what one is and therefore struggle to consume them. Podcasts are really geared towards devices that do not have internet connectivity. Imagine a runner that wants to listen to national public radio while he runs but he runs at night when a radio wont pick up his favorite shows, he also does not have a smartphone or there is no cellphone internet where he runs.. that is when a portable mp3 player, like an iPod and downloading media in podcast format would be optimal.</p>
<p>To be honest however, many people have iPhones or Android's these days and they are connected to a good internet connection pretty much all the time. You can just pull up and listen to or watch what you want at any time. In that case, a podcast format can actually be more cumbersome than other media formats.</p>
<p>If you want to look at one website thats geared towards instant on-demand media delivery, it is YouTube. Just pull up the YouTube app on your phone and start watching. Recently one of our clients who had been running a video podcast for years, also wanted to start up a YouTube channel to allow people quick and easy instant viewing. We had the task of copying all their archival media over to YouTube. If someone's been publishing an episode a week for a couple of years, that is a lot of episides to copy over.</p>
That is what prompted the subject of this article and the creation of a tool that will automatically "convert" a video podcast into a YouTube channel. "Convert" isn't really the right word, its really transporting media from one place to another. Anyway, since the podcast format is so standardized and because YouTube has this thing called an API (that lets programs automatically upload videos), then you'd think it's possible to migrate everything without much human time spent sitting there moving one file after another.
<p>We did some searching and there doesn't seem to be a "service" like this out there, so we started to build one. I'm writing it up here in case anyone else is needing to undertake something like this. You could use what we learned or have us run your podcast through our conversion tool for a low cost. If there's a lot of interest in this, we might productize this so that anyone could just come and use it.</p>

<p>The applications for such a service are interesting. Let's say a church posts a videos of it's Sunday morning service every week (and many do), a tool like this could just automatically check their podcast feed and when a new episide is detected, it could automatically upload it to YouTube.</p>
<p>You need a few components to get something like this to work:</p>
<ol>
<li>If you don't have Zend, you should at least download the part of Zend that will upload to YouTube</li>
<li>You need to have a master file to read the podcast file and orchestrate the whole thing. </li>
<li>If you don't have a premium YouTube account you can't upload more than  10 minutes of video at a time so, if your episodes are longer than that,  you need to install ffmpeg to split your episodes into chunks.</li>
</ol>
<p><strong>Getting Zend sorted out</strong></p>
<p>YouTube has a gateway that lets you programatically upload videos instead of always having to use their website. We started our research by Googling to see how you can write a php script to directly upload videos to YouTube. That got us to this page:</p>
<p><a href="http://code.google.com/apis/youtube/2.0/developers_guide_php.html#Direct_Upload">http://code.google.com/apis/youtube/2.0/developers_guide_php.html#Direct_Upload</a></p>
<p>The page has code samples that you can literally copy and paste and they will work. What you need first is to download and install this Zend package on your server. You grab that here:</p>
<p><a href="http://framework.zend.com/download/gdata/">http://framework.zend.com/download/gdata/</a></p>
<p>Download and decompress the package to your web server. You have to make sure the Zend folder is in your include path (and they have info about that on their page). Once you've got that sorted out you should be fine to go ahead and start tweaking your "master file."</p>
<p><strong>Writing your master file</strong></p>
<p>One thing you have to do before you can move forward is apply for a developer's key with Google in order to be able to upload videos. We won't go into detail on that since it's covered on the Google page. In fact, we won't really cover much of the code that actually uploads to Google since it's already so well documented. What we did was literally copy and paste that portion of code from their page into our code files. We of course did some adjusting and inserting of our own variables but that was it.</p>
<p>Our master file uses php's simplexml functions to load the xml from the podcast feed into a data object. We loop through each item in the feed. First the script tries to download it to the 'videos' folder. We set the script up so that it would do only one "action" each time it is run so that it could be set up as a cron. We preferred this method because it would make the whole process of conversion much more stable and dependable as well as not hammering YouTube's upload api when it comes time to upload.</p>
<p>The next time the script runs, it would find the first video downloaded into the videos folder so it would proceed to start cutting it up. It uses ffmpeg to cut and places the segment file into the "cut" folder. We cut the videos down to 10 minute segments each because for most people, this is the upload limit that YouTube enforces. If you have a premium account then you could do away with this activity all together. So when this script runs the second time it will cut the first 10 minutes from the first file.</p>
<p>The third time the script runs it would see the first 10 minutes has been cut out so it would upload it to YouTube. Once it's done uploading to YouTube it moves that segment to the "done" folder. Essentially the script moves files around in folders to keep track of what has been processed and uploaded to YouTube. This system could be upgraded to a database driven system easily.</p>
<p><strong>How to cut files using ffmpeg - how to install ffmpeg<br /></strong></p>
<p>You have to install ffmpeg on the server this will be run on. You have one of two options. Firstly you could put this on a dedicated or VPS server. We'd recommend that because the bandwidth is probably faster. Or you could put this on a machine in your home/office. If you do not have a premium YouTube account, you have to segment the videos. To install FFMPEG we found a really great guide that we used to do the whole thing:</p>
<p><a href="http://chrisjean.com/2009/01/13/install-ffmpeg-and-ffmpeg-php-on-centos-easily/">http://chrisjean.com/2009/01/13/install-ffmpeg-and-ffmpeg-php-on-centos-easily/</a></p>
<p>Just a note. The only thing we did not do form this guide is the "yum update" - you don't have to do that. You also do not have to install FFMPEG-PHP. Installing that php package only helps you if you want to tell the length of the videos in php or if you want to take thumbnails from the video itself.</p>
<p><strong>Putting it all together</strong></p>
<p>I've provided our sample code here this will likely not work out of the box for you as you'll have to modify places in the code for your system paths, your YouTube credentials, and to suit the length of your video files. We wrote this specifically for our needs but wanted to provide it here. If you can get it to work, great, if you'd like us to run a conversion for you on your podcast, we can probably do that for about $5 a file.</p>
<p>You can download the source package here: <a class="jce_file" title="podcast2youtube.zip" href="http://www.winworld.cc/images/blog/podcast2youtube.zip"><img class="jce_icon" src="http://www.winworld.cc/plugins/editors/jce/tiny_mce/plugins/filemanager/img/ext/zip_small.gif" title="zip" style="border: 0px; vertical-align: middle;" />&nbsp;podcast2youtube.zip<span class=" jce_size">&nbsp;</span></a></p>
<p>If you do use this, please let us know :)</p>
<p> </p>
<style><!--
.php {width:100%; height:300px; overflow:auto;}
--></style>
<pre xml:lang="php"></pre>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Sat, 13 Aug 2011 19:16:43 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/17-blog/249-converting-podcast-to-youtube.html</guid>
        </item>
        <item>
            <title>Our review of Shipwire as a fulfillment partner for Magento Online Stores</title>
            <link>http://www.winworld.cc/blog/26-magento/247-our-review-of-shipwire-as-a-fulfillment-partner-for-magento-online-stores.html</link>
            <description><![CDATA[<p><img style="margin-right: 20px; margin-bottom: 20px; float: left;" alt="240x55-72-3k" src="http://www.winworld.cc/images/blog/240x55-72-3k.gif" height="55" width="240" />When you are developing your new eCommerce solution, you are likely planning to pack and ship orders directly from your in-house facilities. What most people know is that in the world of "fulfillment" there is another choice. Fulfillment is the act of outsourcing that business function with includes both the storage of and the shipping of your orders/products. There are many companies that focus just on shipping and packing and there are also those who provide a full solution of eCommerce blended with fulfillment.</p>
<p>For larger companies of brands such as Nike and Ralph Lauren, their job is not to be experts at fulfillment, their job is to focus on brand and product development. That is why it makes sense for them to work with a fulfillment partner.</p>
<p>In recent months we've reviewed fullfilment resources that are available specifically for medium sized businesses that are using Magento eCommerce. We unturned one called ShipWire that we thought was good enough to blog about here.</p>

<p> </p>
<p>As we have researched a suggested provider, some of the companies we spoke with, such as GSI, said the fulfillment requirements for small to medium sized businesses were too small for them to deal with. For other operations requirements of most medium sized businesses using Magento would actually be too large.</p>
<p>The fulfillment company we recommend is called <a href="http://www.shipwire.com">Shipwire</a>. If you compare the fulfillment requirements of most medium sized businesses to the target market that Shipwire is set up for, there is an obvious correlation. Shipwire has optimized its business to pursue fulfillment volumes from as little as 15 products per month up to 5,000 products. Instead of pursuing large contracts, Shipwire has spread its business out by efficiently filling orders for small to medium sized businesses. They are a large company with warehouse locations throughout the United States.</p>
<p>Another reason that we recommend Shipwire is that they are already 100% integrated with Magento, the ecommerce solution that we most often provide. All data and response notifications will be handled by their pre-existing connectivity. In choosing a fulfillment provider you will likely want to choose one that has an established track record, a veteran in fulfillment that is going to expertly handle all of your orders.</p>
<p>We believe, based on our research of their performance, that most companies would definitely find this through Shipwire and we would encourage you to take a look at the strength of service offerings that Shipwire can provide at a remarkable value.</p>
<p>If you choose another provider for fulfillment, note that you would probably have to custom code all of the interfaces and data connectivity with Magento to meet their needs.</p>]]></description>
            <author> jase.clamp@winworld.com (Jase Clamp)</author>
            <pubDate>Fri, 22 Jul 2011 18:26:33 GMT</pubDate>
            <guid isPermaLink="false">http://www.winworld.cc/blog/26-magento/247-our-review-of-shipwire-as-a-fulfillment-partner-for-magento-online-stores.html</guid>
        </item>
    </channel>
</rss>
