<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Slicksurface - Tech, Design &amp; SEO Blog</title>
	
	<link>http://www.slicksurface.com/blog</link>
	<description>Observations about technology, design, and search engine optimization by the staff of Slicksurface LLC - a design and technology company located in New York.</description>
	<lastBuildDate>Mon, 28 Sep 2009 17:55:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/slicksurface" /><feedburner:info uri="slicksurface" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>40.85777</geo:lat><geo:long>-73.93485</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/2.0/</creativeCommons:license><image><link>htttp://www.slicksurface.com/</link><url>http://www.slicksurface.com/resources/logos/feed-logo.jpg</url><title>Slicksurface LLC</title></image><item>
		<title>Partners With Parents Tutoring Service Launches New Site</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/7HOBE3zAMjw/partners-with-parents-tutoring-service-launches-new-site</link>
		<comments>http://www.slicksurface.com/blog/2009-09/partners-with-parents-tutoring-service-launches-new-site#comments</comments>
		<pubDate>Mon, 28 Sep 2009 17:36:28 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Feeds]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Search Marketing]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[Feedburner]]></category>
		<category><![CDATA[SEO/SEM]]></category>
		<category><![CDATA[Web Analytics]]></category>
		<category><![CDATA[web-site-design]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=316</guid>
		<description><![CDATA[Slicksurface recently launched a new website for Partners With Parents Tutoring Service, located in New York City. This site was a particularly interesting project for a number of reasons.
Jesse Gerber, co-founder of Partners With Parents is a neighbor and good friend. He was initially resistant to a redesign partly due to the cost of the [...]]]></description>
			<content:encoded><![CDATA[<p>Slicksurface recently launched a new website for <a href="http://www.partnerswithparents.com">Partners With Parents Tutoring Service</a>, located in New York City. This site was a particularly interesting project for a number of reasons.</p>
<p><a title="Jesse Gerber biography" href="http://www.partnerswithparents.com/about-us/staff-biographies">Jesse Gerber</a>, co-founder of Partners With Parents is a neighbor and good friend. He was initially resistant to a redesign partly due to the cost of the redesign and implementation and partly due to a certain level of fear of how a new website might change the nature of his business.  The focus of his fear was the possibility of an overwhelming number of inquiries without the necessary support or conversion to real customers. After much conversation, we began the redesign process over the summer.<span id="more-316"></span></p>
<p>We decided to go with a <a href="http://www.wordpress.org">WordPress-driven website</a>, which would give the company the flexibility to change the content on their own, without them needing to come back to us every time they wanted to update a page, or add new information.</p>
<p>Partners With Parents has been in business for over a decade. They specialize in custom private tutoring, with the tutors preparing lessons suited to the each individual's needs and educational environment. They have also had much <a title="test prep tutoring" href="http://www.partnerswithparents.com/services/test-preparation" target="_self">success in test preparation</a>, like the SAT, Regents, AP tests, GRE, MCAT, LSAT and others. Additionally they have <a title="Experienced homeschooling service" href="http://www.partnerswithparents.com/services/homeschooling">extensive experience in homeschooling</a> children with special needs and unique situations.</p>
<p>I took this opportunity to begin a program of my own, an internship program for my web design students. A talented student, Nusrat Bintun, was Slicksurface's first intern. She showed great initiative, and where she lacked in skill and experience, she made up for with enthusiasm and consistency. She was particularly involved with helping to develop the illustrations used on the site. By the end, she gained additional skills in photoshop and illustrator, plus received insight in working with a real client.</p>
<p>An interesting thing to note about this redesign is that it promised to be easy to improve the performance of the site. The previous designer had very little experience creating real professional websites. So instead of designing the pages so that the images were images, and the text was html, he made the text into images as well.  There was basically no text anywhere on the site for the search engines to index.</p>
<p>Two weeks following the launch, we were fully indexed by Google.  We were not indexed by the other search engines, but we knew that would come in time. Partners With Parents immediately ranked for "New York City tutoring" and "NYC tutoring" falling on page 4 and 3 respectively. We now are guiding them in content development to rank for other relevant search terms like "<a href="http://www.partnerswithparents.com/services/homeschooling">New York City homeschooling</a>" and "<a href="http://www.partnerswithparents.com/services/test-preparation">test prep</a>".</p>
<p>Although the site has been indexed fully, the traffic hasn't increased by leaps and bounds in the first month following launch. In studying Google trends, "New York City tutoring" does not have enough data to even warrant a chart. "NYC tutoring" ranks very well with a Brooklyn audience, although "Brooklyn tutoring" does not have enough data to warrant a chart. For just "tutoring" or "tutoring service", the New York audience is in the top 10.</p>
<p>Surprisingly, they immediately received <a href="http://www.partnerswithparents.com/find-a-tutor">requests for tutors</a>, had <a href="http://www.partnerswithparents.com/contact">tutors inquiring about positions</a>, and had subscriptions to the <a href="http://feedburner.google.com/fb/a/mailverify?uri=PartnersWithParents&amp;amp;loc=en_US&quot;">automatic email updates</a> (see description below).</p>
<p>After we have ranked for the key search terms, the next goal is to work towards getting PartnersWithParents.com to show up on the first page for them.</p>
<p>Partners With Parents is looking to build a community among parents, educators, support professionals, and themselves. They decided that one way they would do this is to regularly write posts on everything including <a href="http://www.partnerswithparents.com/tutoring/education">articles about education</a> and <a href="http://www.partnerswithparents.com/tutoring/parenting">parenting</a>, <a href="http://www.partnerswithparents.com/tutoring/new-york-city-families">family challenges and things to do in New York City</a>, and <a href="http://www.partnerswithparents.com/tutoring/stress-and-anxiety">parents and children dealing with stress and anxiety</a>.</p>
<p>Finally, we also implemented <a href="http://www.feedburner.com">Feedburner</a> on this site.  Because we used blog software to run it, the site inherently has a feed.  We've taken advantage of this by inviting users to subscribe to regular updates of the site. Whenever a new blog post is written, those who have subscribed will receive emails automatically of the full blog posts. An inexpensive feature that keeps people reminded of the company's services and expertise.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=7HOBE3zAMjw:-PGP4yY0d0c:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=7HOBE3zAMjw:-PGP4yY0d0c:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=7HOBE3zAMjw:-PGP4yY0d0c:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=7HOBE3zAMjw:-PGP4yY0d0c:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=7HOBE3zAMjw:-PGP4yY0d0c:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=7HOBE3zAMjw:-PGP4yY0d0c:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=7HOBE3zAMjw:-PGP4yY0d0c:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=7HOBE3zAMjw:-PGP4yY0d0c:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/7HOBE3zAMjw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2009-09/partners-with-parents-tutoring-service-launches-new-site/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2009-09/partners-with-parents-tutoring-service-launches-new-site</feedburner:origLink></item>
		<item>
		<title>Clients Who Try To Cut Down The Price</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/VSSxoMM7M6A/clients-who-try-to-cut-down-the-price</link>
		<comments>http://www.slicksurface.com/blog/2009-06/clients-who-try-to-cut-down-the-price#comments</comments>
		<pubDate>Thu, 04 Jun 2009 16:56:13 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[Business Issues]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=314</guid>
		<description><![CDATA[One of the things I learned many years ago was that if a client balks at the price, they're a problem client. There are exceptions, of course, but some clients do this routinely - they're the ones I'm talking about. IMHO, those clients are almost never profitable.
The same can be true of clients who just [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things I learned many years ago was that if a client balks at the price, they're a problem client. There are exceptions, of course, but some clients do this routinely - they're the ones I'm talking about. IMHO, those clients are almost never profitable.<span id="more-314"></span></p>
<p>The same can be true of clients who just can't afford you. They want a $15,000 web site for $4,000 and they think they're spending a lot and should get all the bells and whistles. Again, there are exceptions to that rule as well, but generally it's true. The exception are people who understand your value, but can't afford you, but make it clear they're really grateful that you're cutting them a deal. But they're maybe 1 in 20 people in this group.</p>
<p>Here's a video from YouTube that puts a funny slant on it. If you prefer, you can <a href="http://www.youtube.com/watch?v=R2a8TRSgzZY" target="_blank">watch it in HD</a> on YouTube...</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="560" height="340" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/R2a8TRSgzZY&amp;hl=en&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="560" height="340" src="http://www.youtube.com/v/R2a8TRSgzZY&amp;hl=en&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>In these dire economic times it's tempting to take on clients - even when they can't come close to affording you. We had to turn down an interesting project lately because we got this sorta bad vibe off it. Just be careful - you may be better turning down the work.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=VSSxoMM7M6A:ZaC2m8Sxmsg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=VSSxoMM7M6A:ZaC2m8Sxmsg:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=VSSxoMM7M6A:ZaC2m8Sxmsg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=VSSxoMM7M6A:ZaC2m8Sxmsg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=VSSxoMM7M6A:ZaC2m8Sxmsg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=VSSxoMM7M6A:ZaC2m8Sxmsg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=VSSxoMM7M6A:ZaC2m8Sxmsg:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=VSSxoMM7M6A:ZaC2m8Sxmsg:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/VSSxoMM7M6A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2009-06/clients-who-try-to-cut-down-the-price/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2009-06/clients-who-try-to-cut-down-the-price</feedburner:origLink></item>
		<item>
		<title>How Can Yahoo!’s Spam Filter Be THIS Bad?</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/X32rVXGPIKg/how-can-yahoos-spam-filter-be-this-bad</link>
		<comments>http://www.slicksurface.com/blog/2009-05/how-can-yahoos-spam-filter-be-this-bad#comments</comments>
		<pubDate>Sat, 30 May 2009 14:06:19 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[Spam]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=306</guid>
		<description><![CDATA[Please explain to me how it is that Yahoo! can't figure out that the following e-mail messages are spam... It boggles my mind...
Example 1:
From: Jasmine Carter &#60;eshulsenerman55@yahoo.co.uk&#62; (was this sent from Yahoo! mail? Wouldn't the user hve a bad history?)

Subject: PrettybtP0rn0qshotswz NkLwEcPfjuBSvtYzMh
Body: http://74ce532cee461e8c.faceplanesize.com!}TrKbR3ineUtLzxINIU   PJBgeXVHxUdnRToTQMqagL
Example 2: 
From: Shelby Taylor &#60;garlettabearden94@yahoo.co.uk&#62; (again, a yahoo.co.uk e-mail [...]]]></description>
			<content:encoded><![CDATA[<p>Please explain to me how it is that Yahoo! can't figure out that the following e-mail messages are spam... It boggles my mind...</p>
<p><strong>Example 1:</strong></p>
<p><em>From:</em> <span class="cgSelectable" title="View all messages from this sender">Jasmine Carter &lt;eshulsenerman55@yahoo.co.uk&gt; (was this sent from Yahoo! mail? Wouldn't the user hve a bad history?)<br />
</span></p>
<p><em>Subject:</em> <span class="cgSelectable" style="cursor: pointer;" title="View all messages with this subject">PrettybtP0rn0qshotswz NkLwEcPfjuBSvtYzMh</span></p>
<p><em>Body:</em> <a href="javascript:alert('This was a link');"><span id="lw_1243691572_0" class="yshortcuts">http://74ce532cee461e8c.faceplanesize.com</span></a>!}TrKbR3ineUtLzxINIU   PJBgeXVHxUdnRToTQMqagL<span id="more-306"></span></p>
<p><strong>Example 2: </strong></p>
<p><em>From:</em> <span class="cgSelectable cgSelectable-over" title="View all messages from this sender">Shelby Taylor &lt;garlettabearden94@yahoo.co.uk&gt; (again, a yahoo.co.uk e-mail address)<br />
</span></p>
<p><em>Subject:</em> <span class="cgSelectable" style="cursor: pointer;" title="View all messages with this subject">-SEX-U-A-LY_EX-PL_I_C_It SPzNynCLWiTnPJyPJmvU</span></p>
<p><em>Body:</em> NpZnutWnmUdgdZuJZDfUVp{)<a href="javascript:alert('This was a link');"><span id="lw_1243691838_0" class="yshortcuts">dad4479785c30468.yessoontalk.com</span></a>}&amp;bcRREwMbmEcGfdoTH   NgRIcnHXqsmQIZ1T</p>
<p><strong>Example 3: </strong></p>
<p><em>From:</em><span class="cgSelectable cgSelectable-over" title="View all messages from this sender"> F-r_eePodrnoMotionpictureq &lt;karynmarshi86@yahoo.co.uk&gt;</span></p>
<p><em>Subject:</em> [ No Subject ]</p>
<p><em>Body:</em> hzxqipfrguknzsip{<a href="javascript:alert('This was a link');"><span id="lw_1243692096_0" class="yshortcuts">http://13e0754d679f4cd1.questionexamplehouse.com</span></a>}!hjgfarfbHectcGu   rPwwoRWqHyVpqXyPNrcIcVG</p>
<p>I just don't get it. How can their spam filters miss these e-mails? It can't be that hard to write a spam filter to detect messages like these... I wonder if Yahoo! UK isn't having some sort of problem - all the e-mails appear to come from there.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=X32rVXGPIKg:YLBc_Xewf_8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=X32rVXGPIKg:YLBc_Xewf_8:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=X32rVXGPIKg:YLBc_Xewf_8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=X32rVXGPIKg:YLBc_Xewf_8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=X32rVXGPIKg:YLBc_Xewf_8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=X32rVXGPIKg:YLBc_Xewf_8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=X32rVXGPIKg:YLBc_Xewf_8:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=X32rVXGPIKg:YLBc_Xewf_8:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/X32rVXGPIKg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2009-05/how-can-yahoos-spam-filter-be-this-bad/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2009-05/how-can-yahoos-spam-filter-be-this-bad</feedburner:origLink></item>
		<item>
		<title>Changing the look of your page for mobile devices and printing</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/AzWimEn_m7w/changing-the-look-of-your-page-for-mobile-devices-and-printing</link>
		<comments>http://www.slicksurface.com/blog/2008-12/changing-the-look-of-your-page-for-mobile-devices-and-printing#comments</comments>
		<pubDate>Thu, 04 Dec 2008 19:23:03 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Mobile Browsers]]></category>
		<category><![CDATA[CityTech ADV 4850]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=301</guid>
		<description><![CDATA[Your site may look great on screen, but have you thought about what it looks like when it's printed or what it looks like when a mobile device accesses it? Take a moment and print a page from your site - you might be surprised with what comes out of the printer.
If you have white [...]]]></description>
			<content:encoded><![CDATA[<p>Your site may look great on screen, but have you thought about what it looks like when it's printed or what it looks like when a mobile device accesses it? Take a moment and print a page from your site - you might be surprised with what comes out of the printer.<span id="more-301"></span></p>
<p>If you have white or off-white text on a dark background chances are nothing will come out at all since many browsers don't print the background color - so you wind up printing white on white. If your design depends on things like background colors, chances are it won't look the way you want it to when it's printed. Going to a grayscale color palette may cause problems as well. Add to that that Flash areas probably won't print. And the biggest problem may be the width of your web page - not all web browsers shrink the page to fit on the piece of paper and if your page is wider than 675px you may have a serious problem.</p>
<p>When it comes to mobile devices there are a number of issues...</p>
<p>While the iPhone and some other devices can deal with full size web pages, many can't, an even for devices that can it requires a lot of zooming in and zooming out and can be a bad user experience for the customer.</p>
<p>Then there's the issue of the "weight" of a page. With broadband connections being pretty standard for computers these days web designers don't think about the weight of their pages, but for mobile devices it's critical - most are on super slow network connections and even ones with 3G capabilities may not be in a location that has 3G speeds.</p>
<p>And lastly, people on mobile devices are generally looking for different things than people who are on a computer. They're far more likely to be looking for an address or phone number than a person using a computer.</p>
<p>The reason why printing and mobile devices are connected is because the same two strategies are used to address both problems - 1) alternate stylesheets, and 2) alternate pages - which you use really depends on your situation and how good of a solution you want to implement for printing and mobile devices. If you can't imagine anyone ever printing a page from your web site, then you don't need to spend much time implementing a solution.</p>
<p><em>Alternate Stylesheets</em></p>
<p>When you specify a stylesheet in HTML you typically have a link tag that looks like this:</p>
<p>&lt;link rel="stylesheet" href="/resources/main.css" type="text/css"&gt;</p>
<p>If you've done some reading you may know that there's a "media" attribute that can be added to the link tag which would change it to look something like this:</p>
<p>&lt;link rel="stylesheet" href="/resources/main.css" type="text/css" media="all"&gt;<br />
&lt;link rel="stylesheet" href="/resources/screen.css" type="text/css" media="screen"&gt;<br />
&lt;link rel="stylesheet" href="/resources/print.css" type="text/css" media="print"&gt;<br />
&lt;link rel="stylesheet" href="/resources/mobile.css" type="text/css" media="handheld"&gt;</p>
<p>The media attribute is the key to what we're talking about here. In the example above styles that will be used in all circumstances are defined in main.css. Styles that will only be used on computers are defined in screen.css. Styles that are only used for printing in print.css. And lastly styles that are only used by mobile devices in mobile.css. So when displayed on a computer main.css and screen.css will be loaded and print.css and mobile.css will be ignored, and so on...</p>
<p>Now think about the things you might want to change depending on how it's being used... Since you can't click on a nav bar on a printed page, you may want to hide them completely with display:none when printing. Or you may want to change the width of the page from an absolute value to 100% for printing and mobile devices. Or you may eliminate things like background images for printing and mobile devices. There's a lot you can customize.</p>
<p><em>Alternate Content</em></p>
<p>While having an alternate stylesheet is a quick and easy way to customize the look and feel for printing or mobile devices and it's usually better than doing nothing at all, it's often inadequate. The issue is the HTML document you're working with. You may not be able to do everything you want to do with CSS, or the page may just be too heavy to do well on a mobile device.</p>
<p>Remember, the general rule is to shoot for a total page weight (including CSS and graphics) of less than 20Kb when making a page for mobile devices. Pages over that weight will be penalized by the mobile search engines.</p>
<p>In fact there are many factors you should take into consideration when designing a page for a mobile device. The nav bar is just one example - it should be kept simple and put at both the top and bottom of the page, and possibly interspersed in the middle of the page if the page is long. There's a lot to properly designing a page for a mobile device (including special doc types). I highly recommend you read up on the subject before you go and spend time doing it the wrong way.</p>
<p>To implement an alternate page for printing or for a mobile device once again you use a link tag, but this time it's not rel="stylesheet" it's rel="alternate" and will look something like this...</p>
<p>&lt;link rel="alternate" media="print" type="text/html" href="/image/detail-print.htm?variantid=2983" /&gt;</p>
<p>To see that in action. The original page was <a href="http://www.netterimages.com/image/2983.htm" target="_blank">a page on Netter Images showing an illustration of malignant tumors</a>. <a rel="nofollow" href="http://www.netterimages.com/image/detail-print.htm?variantid=2983" target="_blank">The alternate page used for printing</a> scales the image down, uses desaturated header graphics, and presents the data on the page in a less interactive manner that looks like a printed document.</p>
<p>One thing you should be concerned with is the issue of duplicate content. For alternate versions used for printing, you'll want to either specify nofollow in a robots meta tag, or block access to the file completely with robots.txt. With mobile versions it's more complicated because you want spiders to crawl, but want the search engine to understand which page is targeted to which audience. You can try to use robots.txt to only allow mobile spiders to see the mobile pages, but that may be more trouble than it's worth.</p>
<p><em>Other Uses</em></p>
<p>Alternate stylesheets and alternate pages are important to the visually handicapped. The same strategies we used here are used to create pages that are friendly to them - just use media="aural". CSS supports "voices" - so you can specify the type of voice you think is approrpriate for you content, etc.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=AzWimEn_m7w:sBnpVSb_dVw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=AzWimEn_m7w:sBnpVSb_dVw:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=AzWimEn_m7w:sBnpVSb_dVw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=AzWimEn_m7w:sBnpVSb_dVw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=AzWimEn_m7w:sBnpVSb_dVw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=AzWimEn_m7w:sBnpVSb_dVw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=AzWimEn_m7w:sBnpVSb_dVw:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=AzWimEn_m7w:sBnpVSb_dVw:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/AzWimEn_m7w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2008-12/changing-the-look-of-your-page-for-mobile-devices-and-printing/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2008-12/changing-the-look-of-your-page-for-mobile-devices-and-printing</feedburner:origLink></item>
		<item>
		<title>Use Apache’s .htaccess To Accomplish Cool And Useful Tasks</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/8gvguuK9dHQ/use-apaches-htaccess-to-accomplish-cool-and-useful-tasks</link>
		<comments>http://www.slicksurface.com/blog/2008-11/use-apaches-htaccess-to-accomplish-cool-and-useful-tasks#comments</comments>
		<pubDate>Thu, 20 Nov 2008 21:09:29 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Site Configuration]]></category>
		<category><![CDATA[CityTech ADV 4850]]></category>
		<category><![CDATA[mod_proxy]]></category>
		<category><![CDATA[mod_rewrite]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=294</guid>
		<description><![CDATA[One of the reasons why Apache is such a popular web server is because it's almost infinitely expandable and flexible. There are some incredibly powerful things you can do with Apache's config settings, and .htaccess is the most common way to modify those settings.
First a little background. .htaccess is the name of the file. Yes, [...]]]></description>
			<content:encoded><![CDATA[<p>One of the reasons why Apache is such a popular web server is because it's almost infinitely expandable and flexible. There are some incredibly powerful things you can do with Apache's config settings, and .htaccess is the most common way to modify those settings.<span id="more-294"></span></p>
<p>First a little background. .htaccess is the name of the file. Yes, it starts with a dot which means on Unix based systems (like Linux and Apple's OS X) the file will be invisible. However, web authoring programs like Dreamweaver make it visible in their programs because they know it's power and importance.</p>
<p>You place the .htaccess file in a directory and the rules in that .htaccess file will affect that directory as well as all the subdirectories of that directory. It should be mentioned that .htaccess is a little inefficient. If you have access to your site's virtual host file, you can do pretty much the same things there more efficiently.</p>
<p>There are far too many things that are possible with .htaccess to discuss all of them here, so we'll just touch on some of the more common and useful things you can do.</p>
<p>One thing we should mention is that .htaccess is often used in combination with mod_rewrite. Apache is a modcular web application. There are probably 20-30 common modules that are used with Apache and mod_rewrite is one of them. mod_rewrite lets you do things to the URLs and based on the URLs. That may sound confusing, but it will make more sense in a moment. When you use mod_rewrite you need to have a line that reads:</p>
<p><code>RewriteEngine On</code></p>
<p>I'll be putting that in each of the examples, but when you use the code from this page you only need to have that line once in your .htaccess file - before the first mod_rewrite command.</p>
<p>The other thing I want to mention is that mod_rewrite is based on "regular expressions". If you really want to get into using mod_rewrite I suggest getting a book on regular expressions. You want a book that's concise and to the point since regular expresssions can get pretty complicated, but the basics are pretty straightforward.</p>
<p><em>Enforcing a canonical domain name</em></p>
<p>As you may know you can have often leave the www. out of a URL and the URL will work fine. The problem is that if you let people get to your site however they want and don't enforce either always having www or always not having www the search engines may think www and non-www are two different sites, since that's theoretically possible and was true in the early days of the world wide web. The problem with the search engines thinking you have two sites instead of one is that the authority of your site will be split and you'll have duplicate content issues. In fact the seach engine may even think one site is stealing content from the other site. The bottom line is that the search engines get confused and it's never good to get search engines confused.</p>
<p>The way to fix this with .htaccess is to have a statement that looks like this...</p>
<p><code>RewriteEngine On<br />
RewriteCond %{HTTP_HOST} !^www\.slicksurface\.com$<br />
RewriteRule ^(.*)$ http://www.slicksurface.com$1 [R=301,L]</code></p>
<p>Notice there is a RewriteCond line and a RewriteRule line. There will always be a RewriteRule line with mod_rewrite, and there can be zero or many RewriteCond lines. Think of RewriteCond as defining conditions that must be met before executing the rule.</p>
<p>You may know from scripting languages like Javascript that an ! means "not". Add to that the regular expression syntax ^ means "starts with" and $ means "ends with" and the first line is saying if the HTTP_HOST is NOT www.slicksurface.com. The backslashes are just there because the periods need to be escaped. And you should know (or at least guess) that HTTP_HOST is the <a href="http://www.slicksurface.com/blog/2008-09/php-101-using-apache-envirnoment-variables">Apache environment variable</a> that tells you the host name of the site.</p>
<p>So it's going to do something if the site name is now www.slicksurface.com - that 'something' is defined in the second line. (.*) is the way in regular expressions that you grab a bunch of characters. So ^(.*)$ is saying everything from the start to the end. But realize that RewriteRule acts on only the part of the URL that's in youru directory. So if you put the .htaccess file in http://www.slicksurface.com/blog/ Then it would be working on anything that came after that in the URL.</p>
<p>OK, so it's grabbed everything in the URL (not including the host name) and the second part of the second line uses $1 to tack that onto the end of http://www.slicksurface.com. The third part (the portion in brackets) tells Apache that you want to do a 301 (permanent) redirect (R=301), and that RewriteRule is the last line in what you're trying to do (L).</p>
<p>So try it out... Click on this link and see where you go...</p>
<p><a href="http://slicksurface.com/blog/" target="_blank">http://slicksurface.com/blog/</a></p>
<p>Notice it looks like www. gets added to the URL, which is basically true (in fact it wasn't "added" the user was quickly redirected to the URL with the www in it).</p>
<p><em>Page Moved Redirects</em></p>
<p>There are times when you want to move a page from one URL to another. You try to minimize doing these types of things, but sometimes they're just unavoidable. When you do need to move a page you want to put a redirect in place to let search engine spiders and people who may be following links from other sites know that the page has moved and be able to find what they're looking for.</p>
<p>A while back we migrated from using Blogger to using WordPress. This meant that all the URLs changed. We could write a general rule that covered many instances (see below), but some URLs didn't work with the rule. In those cases we had to have a simple RewriteRule to handle the rewrites. Here's an example of one of them...</p>
<p><code>RewriteEngine On<br />
RewriteRule ^2007/04/4d-backup-improves-creation-of-log.html$ http://www.slicksurface.com/blog/2007-04/4d-backup-improves-creation-of-log-files [NC,R=301,L]</code></p>
<p>So, if it's in a .htaccess file in the /blog/ directory, that will take the URL <a href="http://www.slicksurface.com/blog/2007/04/4d-backup-improves-creation-of-log.html" target="_blank">http://www.slicksurface.com/blog/2007/04/4d-backup-improves-creation-of-log.html</a> and redirects it to <a href="http://www.slicksurface.com/blog/2007-04/4d-backup-improves-creation-of-log-files" target="_blank">http://www.slicksurface.com/blog/2007-04/4d-backup-improves-creation-of-log-files</a> - notice that I'm doing a permanent 301 redirect. And lastly, the NC means that the rule is not case sensitive.</p>
<p>There are few ways to do redirects with Apache, but that's how you'd do it with mod_rewrite.</p>
<p><em>Rules To Redirect Pages Based On A Pattern</em></p>
<p>When we migrated from Blogger to WordPress the directory structure went from /blog/YYYY/MM/file.htm to /blog/YYYY-MM/file - that's a pretty easy pattern to migrate and we did so with the following mod_rewrite rule:</p>
<p><code>RewriteEngine On<br />
RewriteRule ^(\d{4})/(\d{2})/(.+)\.html$   http://www.slicksurface.com/blog/$1-$2/$3  [NC,R=301,L]</code></p>
<p>Let's look at this closely. While the regular expression code will probably be beyon your level of expertise - you can see that it's looking for something 4 and then something 2 and you'd be right if you guessed that's the 4 digit year followed by the 2 digit month. In other words (\d{4}) gets a 4 digit numeric string and (\d{2}) a 2 digit numeric string. (.+) is much like (.*) we saw above except (.+) requires that there be characters, where (.*) can work when there's nothing there. By putting those things in parentheses, we can pull them out in the URL we want to redirect to. They simply go in order $1, $2, $3...</p>
<p><em>Making The URL Different Than The File Name &amp; Location</em></p>
<p>Rewriting the URL is the reason mod_rewrite is named what it is. Let's say you have some files on disk but you don't want their folder structure and file names to be the actual URL. An example is <a href="http://www.slicksurface.com/medical-thesaurus/" target="_blank">the MeSH medical thesaurus</a> we put up here on slicksurface.com. It has over a hundred thousand files that needed to be organized in folders, but we didn't want those folders to be part of the URL, so we use mod_rewrite to accomplish our goal.</p>
<p>Let's take an example... We have the page on "Fungi" which has the following URL:</p>
<p><a href="http://www.slicksurface.com/medical-thesaurus/descriptor/D005658/fungi.htm" target="_blank">http://www.slicksurface.com/medical-thesaurus/descriptor/D005658/fungi.htm</a></p>
<p>But there's no actual document named fungi.htm in a folder named D005658. Instead the real file is at:</p>
<p><a rel="nofollow" href="http://www.slicksurface.com/medical-thesaurus/descriptor/8/D005658.htm" target="_blank">http://www.slicksurface.com/medical-thesaurus/descriptor/8/D005658.htm</a></p>
<p>What I did was randomize the files into 10 directories based on the last number in their ID. Then when I write files that refer to those files I add on the title of the page as a fake file name.</p>
<p>Here's the mod_rewrite syntax:</p>
<p><code>RewriteEngine On<br />
RewriteRule ^descriptor/D(\d\{5})(\d)/   descriptor/$2/D$1$2.htm [L]</code></p>
<p>So what that did was serve one file when another file was requested. If you notice the virtual file name isn't used at all, so the following URL would work just as well...</p>
<p><a rel="nofollow" href="http://www.slicksurface.com/medical-thesaurus/descriptor/D005658/foo.htm" target="_blank">http://www.slicksurface.com/medical-thesaurus/descriptor/D005658/foo.htm</a></p>
<p>Another thing you might notice is no $ was used - we just defined the beginning of the pattern and that was enough.</p>
<p><em>Having One Template Control Everything In A Directory</em></p>
<p>Another example similar to the one we just covered is having a single template control all the URLs for a directory. For example, let's say you have a file named index.php that takes a GET parameter of 'id'. The URL might look something like this if you were calling the template directly:</p>
<p>http://www.slicksurface.com/test/index.php?id=1234</p>
<p>But you don't want to have it look like that, you want the URLs to look like this:</p>
<p>http://www.slicksurface.com/test/1234.htm</p>
<p>All the numbered pages don't have to actually exist - all those URLs can be passed onto the template using something like the following:</p>
<p><code>RewriteEngine On<br />
RewriteRule ^(.+).htm index.php?id=$1</code></p>
<p>Using a strategy like that can be very powerful and let you have one PHP template that can be thousands of URLs that are more search engine friendly than index.php?id=1234. You can do something similar with text, but it's more complicated to handle things like spaces and special characters.</p>
<p><em>Serving Pages From Other Sites As URLs On Your Site</em></p>
<p>.htaccess can be used with more than mod_rewrite. Another use is with mod_proxy. mod_proxy pulls pages from other sites and can show them as pages on your site, though there are some issues.</p>
<p>Let's take the following page on Dan Wong's site - it's the home page for the advanced web site design course.</p>
<p><a href="http://www.dan-wong.com/advanced-web-design.htm" target="_blank">http://www.dan-wong.com/advanced-web-design.htm</a></p>
<p>Here's a mod_rewrite rule that has the P parameter specifying that it's a mod_proxy situation, not a redirect.</p>
<p><code>RewriteEngine On<br />
RewriteRule ^test/adv-3650$ http://www.dan-wong.com/advanced-web-design.htm [P,L]</code></p>
<p>With that you can see the content of the page at the following URL:</p>
<p><a rel="nofollow" href="http://www.slicksurface.com/test/adv-3650" target="_blank">http://www.slicksurface.com/test/adv-3650</a></p>
<p>But notice that the page doesn't look right. That's because it's not being served from the correct site, so all of the links to stylesheets and images are broken. If he had started all of the references with http://wwww.dan-wong.com/... then the page would actually look correct.</p>
<p>When this is useful is when you have an web application server that is responsible for some, but not all of the files on your website. In that case you can proxy the web application server, pehaps through a secure firewall, and because it's part of an overall system, where the web application server may actually think it is the entire site, the pages will render correctly.</p>
<p>You don't have to use mod_rewrite to use mod_proxy. Here is an example of a mod_proxy statement that you might find in an .htaccess file:</p>
<p><code>ProxyPass customer/ http://127.0.0.1:8080/customer/</code></p>
<p>That will pass all of the URLs from the customer directory onto a web application server that's responding to the 8080 port on the same machine as the web site.</p>
<p><em>Excluding Directories From Being Controlled by WordPress</em></p>
<p>WordPress controls everything in the directory it's installed in. If you want to have say a resources directory that WordPress doesn't control, or a robots.txt file that WordPress doesn't control, then you can use something like this:</p>
<p><code>RewriteEngine On<br />
RewriteCond %{REQUEST_URI} !^resources/<br />
RewriteCond %{REQUEST_URI} !^robots.txt<br />
RewriteCond %{REQUEST_FILENAME} !-f<br />
RewriteCond %{REQUEST_FILENAME} !-d<br />
RewriteRule . index.php [L]</code></p>
<p>The bottom three lines are standard for WordPress, but the top two exclude the resources directory and the robots.txt file.</p>
<p><em>Making HTM Files Execute PHP</em></p>
<p>Sometimes you want to hide the fact that a php file is really a php file, or you just like your URLs to end with .htm rather than PHP. To make it so you can put PHP in .htm files you put the following in the .htaccess file:</p>
<p><code>AddType application/x-httpd-php .htm</code></p>
<p><em>Wrap Up</em></p>
<p>So there's a lot you can do with .htaccess files. Chances are if you're hitting a wall and need to do something special there's a way to do it with an htaccess file.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=8gvguuK9dHQ:_10Ao_9IeEE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=8gvguuK9dHQ:_10Ao_9IeEE:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=8gvguuK9dHQ:_10Ao_9IeEE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=8gvguuK9dHQ:_10Ao_9IeEE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=8gvguuK9dHQ:_10Ao_9IeEE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=8gvguuK9dHQ:_10Ao_9IeEE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=8gvguuK9dHQ:_10Ao_9IeEE:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=8gvguuK9dHQ:_10Ao_9IeEE:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/8gvguuK9dHQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2008-11/use-apaches-htaccess-to-accomplish-cool-and-useful-tasks/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2008-11/use-apaches-htaccess-to-accomplish-cool-and-useful-tasks</feedburner:origLink></item>
		<item>
		<title>How To Do An Outbound Link Script For Affiliate Links To Sponsors</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/i4aXDuEHiGM/how-to-do-an-outbound-link-script-for-affiliate-links-to-sponsors</link>
		<comments>http://www.slicksurface.com/blog/2008-11/how-to-do-an-outbound-link-script-for-affiliate-links-to-sponsors#comments</comments>
		<pubDate>Thu, 13 Nov 2008 21:22:20 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[Advertising]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SEO/SEM]]></category>
		<category><![CDATA[CityTech ADV 4850]]></category>
		<category><![CDATA[PageRank]]></category>
		<category><![CDATA[Paid Links]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=282</guid>
		<description><![CDATA[Having an outbound link script is a good idea for many reason. You can quickly and easily change particular types of links throughout your site. You can control the flow of PageRank, and you can keep search engine spiders away from paid links that they don't want to see. This post goes into how to build an outbound link script using PHP.]]></description>
			<content:encoded><![CDATA[<p>In the last post I discussed <a href="http://www.slicksurface.com/blog/2008-11/how-to-do-rotating-banner-and-text-ads-with-php">how to do a script to randomly display banner ads</a> on a site. The next step is how to handle the clicks on those ads (or on text ads).</p>
<p>You might just think you should embed the links directly in the HTML, but that's often a bad idea. Let's say your sponsor runs a special promotion that uses a special promo link code. You may have the links all throughout your site in blog posts, banner ads, sidebar text ads, etc. There will be too many things to change to take advantage of the special promotion. Having all your outbound sponsor links go through a single script will fix that problem - change things in one place and all your links are changed.<span id="more-282"></span></p>
<p>The way this works is we want to pass into a script URL the ad number (or name) that you want to display. So your URL would look something like this:</p>
<p>http://www.domain.com/scripts/ad-links.php?adid=1234</p>
<p>So ads.php is the script we'll create, and adid is the ad ID for your outbound link.</p>
<p>Sometimes you have to enter other parameters into the ad URLs to meet sponsor guidelines, You can do that as well with a URL that looks something like this:</p>
<p>http://www.domain.com/scripts/ad-links.php?adid=1234&amp;param1=ABC&amp;param2=XYZ</p>
<p>So in that case the sponsor is asking for other information that may vary depending on the context of the ad, so there are two parameters that you can pass into the script which you can insert into the code displaying the banner ad - param1 and param2.</p>
<p>Now, before you start it's a good idea to think about what you want to do with search engine spiders. Search engine spiders don't want to see paid links and affiliate links to sponsors definitely fall into the "paid links" category. You have two options. One is to exclude them completely using robots.txt, the other is to let them crawl the links, but send them to a different URL than a real customer would go to - send them to a relevant page on one of your own sites.</p>
<p>So, let's say your link is to a company that sells pop corn. The best page to send the search engine spider to would be the tag page on your blog that has all the posts about the different types of pop corn offered by the company in question. If you don't have a page like that then you could send them to the page with all the posts about their company or a page with all the different pop corn reviews you might have. The point is, keep it relevant. If you keep it relevant the search engines shouldn't say you're cloaking. If you don't have a relevant page, then 302 them to the main page of your site. The 302 redirect doesn't pass page rank, so this should be a harmless way of keeping them away from paid links without them thinking your playing page rank sculpting games to deceive them.</p>
<p>Now, onto the script... Here's a brief version of the script:</p>
<p><code>&lt;?php<br />
if (stripos($_SERVER['HTTP_USER_AGENT'], 'googlebot') &gt; 0) { $spider = TRUE; }<br />
elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'msnbot') &gt; 0) { $spider = TRUE; }<br />
elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'teoma') &gt; 0) { $spider = TRUE; }<br />
elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'slurp') &gt; 0) { $spider = TRUE; }<br />
else { $spider = FALSE; }<br />
/* Pop Corn Sponsor */<br />
if (($_GET['adid'] == 1) &amp;&amp; ($spider)) { header("Location:http://www.your-domain.com/tag/pop-corn-sponsor-posts",TRUE,301); }<br />
elseif ($_GET['adid'] == 1) { header("Location:http://join.pop-corn-sponsor.com/track/ODM4NzA1NzozMzoxNQ/",TRUE,302); }<br />
/* Pop Corn Maker Sponsor */<br />
elseif (($_GET['adid'] == 2) &amp;&amp; ($spider)) { header("Location:http://www.your-domain.com/</code><code>",TRUE,302); }<br />
elseif ($_GET['adid'] == 2) { header("Location:http://</code><code>join.pop-corn-machine-sponsor.com</code><code>/track/ODM4NzA1NzozMzoxNg/",TRUE,302); }<br />
else</code><code><br />
</code><code>header("HTTP/1.0 404 Not Found");<br />
</code><code>echo "&lt;html&gt;&lt;head&gt;&lt;title&gt;Link Error&lt;/title&gt;&lt;/head&gt;&lt;body&gt;Link Error&lt;br /&gt;".$_GET['lnk']."&lt;br /&gt;".$_SERVER['HTTP_USER_AGENT']."&lt;/body&gt;&lt;/html&gt;";<br />
?&gt;</code></p>
<p>You can see why we started with a discussion of search engine spiders - it's the first thing the script deals with - the first if statement tests to see if the request is coming from one of the 4 big search engine spiders. If so, it sets the $spider variable to a value of TRUE.</p>
<p>Then there's a if, elseif statment where we go through all the possible adid values. There are two cases for each value - one for what do do with a spider, and the other for what do do with regular users. The PHP header function is used to do 301 (permanent) and 302 (temporary) redirects. Notice that I always send people off to other sites with 302 redirects (so no PageRank is given to the sponsors site), and I also use 302 redirects when I don't have a good page on one of my sites to send spiders. 301 redirects are only used for relevant redirects for spiders so PageRank doesn't accumulate in the redirect script itself.</p>
<p>And lastly there's an else case for what to do if I don't find the adid. First I want to indicate that the link was not found with a 404 (page not found) response code. This makes sure the error will show up as an error in my analytics. Next, I want to tell the user what happened with some very simple HTML code.</p>
<p>So there you have it - an outbound link script that's easy to maintain and SEO friendly.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=i4aXDuEHiGM:8OXpIS5Y1gY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=i4aXDuEHiGM:8OXpIS5Y1gY:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=i4aXDuEHiGM:8OXpIS5Y1gY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=i4aXDuEHiGM:8OXpIS5Y1gY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=i4aXDuEHiGM:8OXpIS5Y1gY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=i4aXDuEHiGM:8OXpIS5Y1gY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=i4aXDuEHiGM:8OXpIS5Y1gY:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=i4aXDuEHiGM:8OXpIS5Y1gY:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/i4aXDuEHiGM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2008-11/how-to-do-an-outbound-link-script-for-affiliate-links-to-sponsors/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2008-11/how-to-do-an-outbound-link-script-for-affiliate-links-to-sponsors</feedburner:origLink></item>
		<item>
		<title>How To Do Rotating Banner And Text Ads With PHP</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/bl1OPo5MDnk/how-to-do-rotating-banner-and-text-ads-with-php</link>
		<comments>http://www.slicksurface.com/blog/2008-11/how-to-do-rotating-banner-and-text-ads-with-php#comments</comments>
		<pubDate>Thu, 13 Nov 2008 20:28:22 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[Advertising]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Banner Ads]]></category>
		<category><![CDATA[CityTech ADV 4850]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=272</guid>
		<description><![CDATA[Rotating banner ads are extremely useful and far more effective than static ads that people quickly ignore as "visual noise". This post shows you an easy way to write a script that can put random banner ads on your site without needing a database or complicated third party solution.]]></description>
			<content:encoded><![CDATA[<p>If you want to have content on your site that changes every time someone loads the page there are a number of possible solutions. Most typically these are ads - either textual or graphical "banner ads", but the same solution can be used for other random content.</p>
<p>There are ad packages/"scripts" out there which are decent, but you should choose them carefully since moving to anything else will be time consuming once you're fully set up (so make sure you really like the package and it's easy to maintain before investing too much energy in it). The other problem with ad packages is that they're almost always database driven and I've frequently seen problems where they don't redirect the person correctly. So check out sites that use the ad package to make sure it works in the real world.<span id="more-272"></span></p>
<p>There are two elements to handling ads - displaying the ad, and handling the click. This post will just address displaying the ad. I'll do another post on <a href="http://www.slicksurface.com/blog/2008-11/how-to-do-an-outbound-link-script-for-affiliate-links-to-sponsors">how you can handle the outbound link</a>. The advantages of what I'm going to show here are:</p>
<ul>
<li>It's something you write and maintain yourself - that means you can customize it as you see fit. It's not some scary black box you don't really understand.</li>
<li>It's not database driven - that means it will be more reliable. It also means it has limitations - if you've got a very large number of ad types (say over 1,000), you should be using a database driven solution.</li>
</ul>
<p>The script is just a big if elseif statement. We're going to add in two features to the idea of a random banner ads - 1) static ads on certain pages, 2) special parameters for certain ads.</p>
<p>Here's a brief version of the script:</p>
<p><code>&lt;?php<br />
$n = rand(1,2);<br />
if ($_SERVER['SCRIPT_NAME']=="/tags/rays-great-popcorn")<br />
{<br />
</code><code>echo "&lt;a href="http://www.your-domain.com/scripts/ad-links.php?adid=41" onclick="javascript:pageTracker._trackPageview('/outbound/rays-great-popcorn');" target="rgpc"&gt;&lt;img border="0" src="http://www.your-domain.com/resources/bnrs/rays-great-popcorn-600-200.jpg" alt="Ray's Great Popcorn" width="600" height="200"&gt;&lt;/a&gt;";<br />
</code><code>}<br />
elseif ($n==1)<br />
{<br />
echo "&lt;a href="http://www.your-domain.com/scripts/ad-links.php?adid=41" onclick="javascript:pageTracker._trackPageview('/outbound/rays-great-popcorn');" target="rgpc"&gt;&lt;img src="http://www.your-domain.com/resources/bnrs/rays-great-popcorn-600-125.jpg" alt="Ray's Great Popcorn" width="600" height="125"</code><code> border="0"</code><code>&gt;&lt;/a&gt;";<br />
}<br />
</code><code>elseif ($n==2)<br />
{<br />
echo "&lt;a href="http://www.your-domain.com/scripts/ad-links.php?adid=41&amp;param1=".$_GET['param1']."" onclick="javascript:pageTracker._trackPageview('/outbound/freds-great-popcorn');" target="fgpc"&gt;&lt;img src="http://www.your-domain.com/resources/bnrs/freds-great-popcorn-600-125.jpg" alt="Fred's Great Popcorn" width="600" height="125"</code><code> border="0"</code><code>&gt;&lt;/a&gt;";<br />
}<br />
</code><code>else{ }<br />
?&gt;</code></p>
<p>So let's go over what the script does... First, it sets a random number into the $n variable. Since we have two ads, it randomly picks a number between 1 and 2. Obviously as you add more cases for more ads, you'd up 2 to a bigger number.</p>
<p>Then it tests to see if we're on the page with the URL /tags/labels/rays-great-popcorn and if so, it displays a special ad that was made just for that page. That page doesn't get a random ad, it always gets that particular ad.</p>
<p>In the next two cases it checks the random number and randomly displays one of the two banner ads you have for your site (of course you'd have more than two).</p>
<p>In the second case it uses a special extra parameter in the outbound URL for the banner ad (param1). It uses PHP's $_GET array to pull the param1 element out of the array. The $_GET array holds all the query parameters you passed in the URL string when you did the include that called the script (we'll show that in a moment). That means that you have to pass all the parameters into the script that you might use in any of the random ads.</p>
<p>The way the script was written was with echo, which meant all the double quotes in the HTML had to be escaped. You could alternately write the code with multiple PHP statements which may be easier for some people to understand since the HTML is just as it would be in a regular HTML document. This approach also means there's a certain amount of editing you can do in the design mode of Dreamweaver.</p>
<p>The HTML is pretty basic - an image with a link, so when you click on the image you follow the link. The one advanced aspect is the <a href="http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&amp;answer=55597" target="_blank">Google Analytics event tagging</a> that I've added in the link. That registers the outbound click as a page view in your analytics so you can analyze what pages do the best in getting people to click on your ads. [You can also set up a goal so all outbound clicks are seen as "conversions", but that's a topic for another post.]</p>
<p>The script would look like this if you wrote it with multiple statements:</p>
<p><code>&lt;?php<br />
$n = rand(1,2);<br />
if ($_SERVER['SCRIPT_NAME']=="/tags/rays-great-popcorn")<br />
{ ?&gt;<br />
</code><code>&lt;a href="http://www.your-domain.com/scripts/ad-links.php?adid=41" onclick="javascript:pageTracker._trackPageview('/outbound/rays-great-popcorn');" target="rgpc"&gt;&lt;img border="0" src="http://www.your-domain.com/resources/bnrs/rays-great-popcorn-600-200.jpg" alt="Ray's Great Popcorn" width="600" height="200"&gt;&lt;/a&gt;<br />
</code><code>&lt;?php }<br />
elseif ($n==1)<br />
{</code><code> ?&gt;</code><br />
<code> &lt;a href="http://www.your-domain.com/scripts/ad-links.php?adid=41" onclick="javascript:pageTracker._trackPageview('/outbound/rays-great-popcorn');" target="rgpc"&gt;&lt;img src="http://www.your-domain.com/resources/bnrs/rays-great-popcorn-600-125.jpg" alt="Ray's Great Popcorn" width="600" height="125"</code><code> border="0"</code><code>&gt;&lt;/a&gt;<br />
</code><code>&lt;?php </code><code>}<br />
</code><code>elseif ($n==2)<br />
{</code><code> ?&gt;</code><br />
<code> &lt;a href="http://www.your-domain.com/scripts/ad-links.php?adid=41&amp;param1="&lt;?php echo $_GET['param1']; ?&gt;" onclick="javascript:pageTracker._trackPageview('/outbound/freds-great-popcorn');" target="fgpc"&gt;&lt;img src="http://www.your-domain.com/resources/bnrs/freds-great-popcorn-600-125.jpg" alt="Fred's Great Popcorn" width="600" height="125"</code><code> border="0"</code><code>&gt;&lt;/a&gt;<br />
</code><code>&lt;?php </code><code>}<br />
</code><code>else{ }<br />
?&gt;</code></p>
<p>But notice in the last case we had to insert a PHP echo inside the HTML to be able to use param1, so no matter how you write it, there are things that are easier and other things that may be more difficult.</p>
<p>Now, the way either one of those scripts is implemented is to save the script in a file and insert it into the page with a <a href="http://www.slicksurface.com/blog/2008-09/php-101-includes">PHP include</a>. So let's say we named the script banner-ads.php and we put it in an /includes/ directory at the root of our site. The include would look something like this:</p>
<p>&lt;?php include($_SERVER['DOCUMENT_ROOT']."/includes/banner-ads.php?param1=forum"); ?&gt;</p>
<p>So that pulls the file banner-ads.php and passes the value "forum" in as param1. That could be useful if you wanted to know the section of your site that was calling the banner ad - just change the value in each one of your templates (one value for the blog templates, one for the forum templates, etc.) But that could be achieved another way:</p>
<p>&lt;?php $param1="forum"; include($_SERVER['DOCUMENT_ROOT']."/includes/banner-ads.php"); ?&gt;</p>
<p>If you did that, then you wouldn't access the value with the $_GET array in the script, instead you'd just access the $param1 variable directly.</p>
<p>So there you have it - a simple way to implement random banner ads that's rock solid and easy to maintain by anyone with just a little bit of technical skills.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=bl1OPo5MDnk:Kv38Jy6hTg0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=bl1OPo5MDnk:Kv38Jy6hTg0:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=bl1OPo5MDnk:Kv38Jy6hTg0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=bl1OPo5MDnk:Kv38Jy6hTg0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=bl1OPo5MDnk:Kv38Jy6hTg0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=bl1OPo5MDnk:Kv38Jy6hTg0:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=bl1OPo5MDnk:Kv38Jy6hTg0:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=bl1OPo5MDnk:Kv38Jy6hTg0:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/bl1OPo5MDnk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2008-11/how-to-do-rotating-banner-and-text-ads-with-php/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2008-11/how-to-do-rotating-banner-and-text-ads-with-php</feedburner:origLink></item>
		<item>
		<title>Dynamic Content With PHP Arrays (No Databases)</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/fR5g9wIsVe4/dynamic-content-with-php-arrays-no-databases</link>
		<comments>http://www.slicksurface.com/blog/2008-11/dynamic-content-with-php-arrays-no-databases#comments</comments>
		<pubDate>Thu, 06 Nov 2008 19:52:35 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[CityTech ADV 4850]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=274</guid>
		<description><![CDATA[You don't actually need to have a database to have some dynamic content on your site. You can use arrays instead. Let's say you want to randomly show 3 Star Wars DVD box covers from Amazon.com with links to the item on Amazon. To do that you'd need three things - 1) The title of [...]]]></description>
			<content:encoded><![CDATA[<p>You don't actually need to have a database to have some dynamic content on your site. You can use arrays instead. Let's say you want to randomly show 3 Star Wars DVD box covers from Amazon.com with links to the item on Amazon. To do that you'd need three things - 1) The title of the movie, 2) the URL of the box cover, and 3) the link to the item.</p>
<p>You define the values that you'll choose from in PHP arrays. To do that you do something like this...</p>
<p><code>&lt;?php<br />
$titles = array ("Star Wars - Episode I, The Phantom Menace", "Star Wars - Episode II, Attack of the Clones", "Star Wars - Episode III, Revenge of the Sith", "Star Wars Episode IV - A New Hope", "Star Wars Episode V - The Empire Strikes Back", "Star Wars Episode VI - Return of the Jedi", "Star Wars - Clone Wars, Vol. 1", "Star Wars - Clone Wars, Vol. 2");</code></p>
<p>$pageURLs = array("http://www.amazon.com/Star-Wars-Episode-Phantom-Widescreen/dp/B00003CX5P/ref=sr_1_4?ie=UTF8&amp;s=dvd&amp;qid=1225998531&amp;sr=1-4", "http://www.amazon.com/Star-Wars-Episode-Attack-Widescreen/dp/B00006HBUJ/ref=sr_1_7?ie=UTF8&amp;s=dvd&amp;qid=1225998531&amp;sr=1-7", "http://www.amazon.com/Star-Wars-Episode-Revenge-Widescreen/dp/B00005JLXH/ref=sr_1_6?ie=UTF8&#038;s=dvd&#038;qid=1225998531&#038;sr=1-6", "http://www.amazon.com/Star-Wars-Episode-IV-Widescreen/dp/B000FQJAIW/ref=sr_1_5?ie=UTF8&amp;s=dvd&amp;qid=1225998531&amp;sr=1-5", "http://www.amazon.com/Star-Wars-Episode-Versions-Widescreen/dp/B000FQJAJG/ref=sr_1_9?ie=UTF8&amp;s=dvd&amp;qid=1225998531&amp;sr=1-9", "http://www.amazon.com/Star-Wars-Episode-VI-Widescreen/dp/B000FQVX78/ref=sr_1_10?ie=UTF8&amp;s=dvd&amp;qid=1225998531&amp;sr=1-10", "http://www.amazon.com/Star-Wars-Clone-Vol-1/dp/B0006Z2LMO/ref=sr_1_12?ie=UTF8&amp;s=dvd&amp;qid=1225998531&amp;sr=1-12", "http://www.amazon.com/Star-Wars-Clone-Vol-2/dp/B000BCE8Q4/ref=sr_1_14?ie=UTF8&amp;s=dvd&amp;qid=1225999439&amp;sr=1-14");</p>
<p>$imgURLs = array ("http://ecx.images-amazon.com/images/I/51BR3RNVKZL._SL160_AA115_.jpg", "http://ecx.images-amazon.com/images/I/51BGV8AJ4RL._SL160_AA115_.jpg", "http://ecx.images-amazon.com/images/I/51RHXMVH9YL._SL160_AA115_.jpg", "http://ecx.images-amazon.com/images/I/517M4V93K0L._SL160_AA115_.jpg", "http://ecx.images-amazon.com/images/I/510GTNVNYYL._SL160_AA115_.jpg", "http://ecx.images-amazon.com/images/I/51CWJ6PC1KL._SL160_AA115_.jpg", "http://ecx.images-amazon.com/images/I/51A6GEB6SAL._SL160_AA115_.jpg", "http://ecx.images-amazon.com/images/I/51F7C82EDGL._SL160_AA115_.jpg");</p>
<p>$titleCount = count($titles);<br />
$element1 = rand(0, $titleCount-1);<br />
$element2 = rand(0, $titleCount-1);<br />
if ($element2==$element1) {$element2 = rand(0, $titleCount-1);}<br />
$element3 = rand(0, $titleCount-1);<br />
if ($element3==$element1) {$element3 = rand(0, $titleCount-1);}<br />
if ($element3==$element2) {$element3 = rand(0, $titleCount-1);}<br />
?&gt;</p>
<p>So you'll need something like that to initialize the arrays. Then you use them by displaying an image with a link to the page on Amazon.com. The code for the image and link would look something like this..</p>
<p><code>&lt;a href="&lt;?php echo $pageURLs[$element1]; ?&gt;" target="amazon"&gt;&lt;img src="&lt;?php echo $imgURLs[$element1]; ?&gt;" alt="&lt;?php echo $titles[$element1]; ?&gt;" title="&lt;?php echo $titles[$element1]; ?&gt;" /&gt;&lt;/a&gt;</code></p>
<p>So the basic syntax is a <a href="http://www.slicksurface.com/blog/2008-09/php-101-echo-the-command-that-inserts-text">PHP echo</a> that specifies the array and the value of the element of the array. $titles[$element1] means the $title array and the element of the array is the value found in the $element1 variable. If you had put $titles[1] that would be element 1 of the array (which is actually the second element in the array since elements start their counting at zero, not 1).</p>
<p>So let's see it in action...</p>
<p><a href="http://www.amazon.com/Star-Wars-Episode-IV-Widescreen/dp/B000FQJAIW/ref=sr_1_5?ie=UTF8&#038;s=dvd&#038;qid=1225998531&#038;sr=1-5" target="amazon"><img src="http://ecx.images-amazon.com/images/I/517M4V93K0L._SL160_AA115_.jpg" alt="Star Wars Episode IV - A New Hope" title="Star Wars Episode IV - A New Hope" /></a>&nbsp;&nbsp;&nbsp;<a href="http://www.amazon.com/Star-Wars-Clone-Vol-1/dp/B0006Z2LMO/ref=sr_1_12?ie=UTF8&#038;s=dvd&#038;qid=1225998531&#038;sr=1-12" target="amazon"><img src="http://ecx.images-amazon.com/images/I/51A6GEB6SAL._SL160_AA115_.jpg" alt="Star Wars - Clone Wars, Vol. 1" title="Star Wars - Clone Wars, Vol. 1" /></a>&nbsp;&nbsp;&nbsp;<a href="http://www.amazon.com/Star-Wars-Episode-Attack-Widescreen/dp/B00006HBUJ/ref=sr_1_7?ie=UTF8&#038;s=dvd&#038;qid=1225998531&#038;sr=1-7" target="amazon"><img src="http://ecx.images-amazon.com/images/I/51BGV8AJ4RL._SL160_AA115_.jpg" alt="Star Wars - Episode II, Attack of the Clones" title="Star Wars - Episode II, Attack of the Clones" /></a></p>
<p>Now, if you take it a step further, the definition of the arrays can happen in an external file and put into the page with a <a href="http://www.slicksurface.com/blog/2008-09/php-101-includes">PHP include</a>. That file can be written with a database application. Which means you could have a site with dynamic content running without any databases on the web server itself. </p>
<p>There are many uses for this type of thing - imagine a "picture of the day" script, or a banner ad rotating script. The options are pretty wide ranging.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=fR5g9wIsVe4:j5JsEryL7SY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=fR5g9wIsVe4:j5JsEryL7SY:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=fR5g9wIsVe4:j5JsEryL7SY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=fR5g9wIsVe4:j5JsEryL7SY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=fR5g9wIsVe4:j5JsEryL7SY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=fR5g9wIsVe4:j5JsEryL7SY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=fR5g9wIsVe4:j5JsEryL7SY:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=fR5g9wIsVe4:j5JsEryL7SY:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/fR5g9wIsVe4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2008-11/dynamic-content-with-php-arrays-no-databases/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2008-11/dynamic-content-with-php-arrays-no-databases</feedburner:origLink></item>
		<item>
		<title>My Personal Thoughts on 4D Summit</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/UPQ4ggFR8AU/my-personal-thoughts-on-4d-summit</link>
		<comments>http://www.slicksurface.com/blog/2008-10/my-personal-thoughts-on-4d-summit#comments</comments>
		<pubDate>Sun, 12 Oct 2008 21:12:42 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[4D]]></category>
		<category><![CDATA[4D Summit 2008]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=266</guid>
		<description><![CDATA[Last year's Summit saw 4D taking a giant leap forward with v11, but it wasn't all there (no 4D Server v11). This year's Summit was more about delivering for the real world and refinement.
4D Server v11 SQL really is pretty cool, and quite powerful. A lot of what it was about was discussed last year, [...]]]></description>
			<content:encoded><![CDATA[<p>Last year's Summit saw 4D taking a giant leap forward with v11, but it wasn't all there (no 4D Server v11). This year's Summit was more about delivering for the real world and refinement.</p>
<p>4D Server v11 SQL really is pretty cool, and quite powerful. A lot of what it was about was discussed last year, but it's interesting to see cases where client/server is actually faster than a standalone/mono application. And most importantly, it's here now - not a demo of an unreleased product.</p>
<p><em>v11.3</em></p>
<p>Then there's v11.3 - If we were back in the v6.0, 6.5, 6.7, 6.8 days v11.3 would be v12 - it really does have some wonderful enhancements in terms of speed, SQL (much improved user management just to name one thing) and SVG (the new component). But the issue, IMHO, is that they didn't completely stabilize v11.2 before doing the enhancements so even 11.3 will probably be a bit of a gamble for a demanding, mission-critical app. At the same time, it's such a big upgrade it is going through a lot of QA, which is always good. It's also good that they said that there will be no new features for v11 after 11.3 - from here on it's all about bug fixes and making the product stable, though I can see them releasing new features as a component like they're doing with SVG.</p>
<p><em>4D Web 2.0 Pack v11 (the AJAX part of it)</em></p>
<p>Even though I'm all about using 4D on the web, and I know some of the guys on the 4D Web 2.0 Pack team personally, I haven't ever felt like I wanted to use 4D Web 2.0 Pack. That opinion changed at Summit this year for two reasons. 1) Brendan's mention of Javascript maturing to the point that incompatibilities aren't as huge as they used to be, and 2) Julien's presentation showed that 4D Web 2.0 Pack v11 really has matured considerably. They've had tools to help you build apps before, but their Green Tea IDE really was a big step in the right direction, though they did stress that it's just how you start your app - it doesn't handle everything you're going to want it to do.</p>
<p><em>Performance</em></p>
<p>That sorta brings up what was the main interest for me this year - performance. I have <a href="http://www.netterimages.com/" target="_blank">a 4D-based web site</a> that gets over 1 million page views a month from real users, plus all the bot traffic (which is considerable - Googlebot alone is over 350,000 pages/month). The client wants to launch another site, integrated with the first one, that will be FAR larger. My rough estimates are that I'll need to support 50 million page views a month within 5 years (that's an <em>average</em> of 20/second). 4D's internal web server can't handle the load I have now, but I need 4D v11 to handle 50 times the current load.</p>
<p>After quizzing Julien Feason and Charlie Vass at a 4D Kitchen session, for high volume uses I need to avoid everything that hits the cooperative thread and hit the database engine as directly as possible - avoiding 4D code whenever possible. That means I have to avoid triggers and the 4D internal web server. Solutions like the AJAX part of 4D Web 2.0 Pack which are based off 4D's internal web sever are a problem - at least for high volume uses. That, and the fact that my client still has IE6 as their corporate standard and 4D Web 2.0 Pack doesn't fully support IE6 means that even though I now <em>want</em> to use AJAX part of 4D Web 2.0 Pack, my use of it will be pretty limited.</p>
<p>However, since you now can hit 4D's database engine directly there are plenty of other options and I'll be rewriting a fair amount of my web app in PHP which can use ODBC to hit 4D's SQL engine without going through 4D code.</p>
<p><em>4D for Flex (part of 4D Web 2.0 Pack v11)</em></p>
<p>While the AJAX part of 4D Web 2.0 Pack is a problem for me, 4D for Flex is a tool I can use, since it hits the preemptive part of 4D directly and it works just fine in IE6 (provided you have Flash 9, which as fate would have Flash 9 isn't part of my client's standard corporate build either). <a href="http://www.slicksurface.com/blog/2008-10/4d-for-flex-v11">The session on 4D for Flex</a> made it seem really complicated, but what I found most interesting about the session were the comments in the last 5 minutes during Q&amp;A... First Tim said that he much preferred working with 4D for Flex than the 4D AJAX framework. Then one of the attendees chimed in saying once you get over the initial learning curve with 4D for Flex you'll love it and think of it as invaluable. He went further saying that the thinking when you work with Flex is more compatible with how you think in 4D than the thinking when working with AJAX.</p>
<p><em>The Language</em></p>
<p>One thing Laurent made very clear (without actually saying it) was that the current 4D language is dead - he literally called it "the old language" (even though there's no "new language" yet). If I understood things correctly, all those lines of code you've written in 4D will never execute in a preemptive multitasking manner. There will be a new language, it will be ECMAScript based (like Javascript and ActionScript), and that will be the language that will work in 4D's preemptive multitasking environment. What this means is that current 4D code, while it will be supported for a long time, is a bit of a liability. If you really want to get the most of 4D in the future you won't be running the code you have now.</p>
<p>From my perspective that means the more I do in PHP and Flex, the better. Remember, with PHP and Flex I can hit the SQL engine directly and use preemptive multitasking now, and the next version of 4D will have a code editor that supports editing PHP files, and a web server (based on Apache) that has a PHP processor built-in. So Laurent's comment last year about triggers being bad was probably more about the language used by triggers being bad. Still, getting away from the 4D language is a huge change in thinking for most of us since the current 4D language is like an old friend.</p>
<p><em>SVG</em></p>
<p>SVG was the pleasant surprise for me at Summit. I've been wrestling with EPS files that have emedded TIFFs. What I realized is that if I get SVG versions of those images I can do all sorts of things like swapping out the TIFF with a low-res JPG and even watermarking the embedded image and translating the text in the image from data.</p>
<p><em>Wrap-Up</em></p>
<p>So, from my perspective it was a useful Summit. 1) It helped clarify strategies to deal with the problems I have now. 2) It let me see that the primary remaining weaknesses in 4D (IMO) are being resolved in the next version.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=UPQ4ggFR8AU:9BEcRcW7oSY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=UPQ4ggFR8AU:9BEcRcW7oSY:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=UPQ4ggFR8AU:9BEcRcW7oSY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=UPQ4ggFR8AU:9BEcRcW7oSY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=UPQ4ggFR8AU:9BEcRcW7oSY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=UPQ4ggFR8AU:9BEcRcW7oSY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=UPQ4ggFR8AU:9BEcRcW7oSY:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=UPQ4ggFR8AU:9BEcRcW7oSY:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/UPQ4ggFR8AU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2008-10/my-personal-thoughts-on-4d-summit/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2008-10/my-personal-thoughts-on-4d-summit</feedburner:origLink></item>
		<item>
		<title>4D Summit Q&amp;A Wrap-Up</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/XLmYsrQNeDQ/4d-summit-qa-wrap-up</link>
		<comments>http://www.slicksurface.com/blog/2008-10/4d-summit-qa-wrap-up#comments</comments>
		<pubDate>Sat, 11 Oct 2008 01:12:44 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[4D]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=248</guid>
		<description><![CDATA[[These are notes from 4D Summit 2008]
Dot notation vs. the language - They've been working on a new language for 4D. They'll be following ECMAScript. It's too early to be specific.
SQL Views - not in v11, but should be in the next version.
Components will have data files in the next version - part of the [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone" style="margin: 5px 8px;" title="Laurent Ribardiere answering questions at 4D Summit" src="http://www.slicksurface.com/blog/resources/2008/10/laurent-223x343.jpg" alt="Laurent Ribardiere answering questions at 4D Summit" width="223" height="343" align="right" />[These are notes from 4D Summit 2008]</p>
<p>Dot notation vs. the language - They've been working on a new language for 4D. They'll be following ECMAScript. It's too early to be specific.</p>
<p>SQL Views - not in v11, but should be in the next version.</p>
<p>Components will have data files in the next version - part of the concept of a project.</p>
<p>QuickReports - they're being actively discussed at 4D France. They're thinking about a web-based interface that also works offline, but nothing definite yet. Still, it's safe to say there's a major upgrade coming.</p>
<p>Array of blobs will come with the new language. The problem with the current version is that characters within blobs use array element notation, so it's confusing to the compiler. However, in 11.2 you can use an array of pictures and put blobs in them.</p>
<p>They will be going back and improving 4D Write.</p>
<p>List boxes can how have multiple lines of text per cell - just put a carriage return (v11.3).</p>
<p>Plugins will change substantially with the new language. DLLs will be directly supported. At the same time there will be backwards compatibility with v11 plugins.</p>
<p>4D Draw functionalities will be replaced with SVG-based tools. There will not be any 4D Draw command-compatible tools.</p>
<p>They're working on 4D Server to 4D Server replication. They're dealing with issues around unique IDs and tools to determine what has changed between two snapshots. The tools will be programmer-oriented, not end-user oriented.</p>
<p>There are plans to have dynamically created objects on a form, Laurent R. keeps asking Laurent E. to get it done and it keeps not getting done  <img src='http://www.slicksurface.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />    (the next version)</p>
<p>There are plans to change the user environment - navigating tables, etc. They want the UI to be web-like.</p>
<p>No new features in v11, after v11.3. Bug fixes are the near-term priority.</p>
<p>No plans to provide jdbc driver for v11, but it shouldn't be too difficult to port what's done in 4D for Flex to Java since the languages are similar. They think it would take about a month, but they don't want to do it or support it.</p>
<p>No 4D Open for v11.</p>
<p>If you have several 4D Servers running on the same machine don't use the automatic memory management it will cause the 4D Servers to fight with each other.</p>
<p>They will reintroduce the ability to have data segments and say which tables are stored in which segment and where you want to store large objects (text, pictures, blobs). Maybe in the next version.</p>
<p>In the next version the server will be faceless and run as a service.</p>
<p>Can't promise 4D Server running on other platforms, but they have plans.</p>
<p>The application server port is the "old way" (cooperative). The DB4D port is the access to the multithreaded part of the application. The old port will remain for a long time since there are many lines of code written in the current language.</p>
<p>You can have too much cache on both v2004 and v11, but for different reasons. On v11 the reason is because you may starve other things running on the server because cache is forced into physical memory. Cache can be in virtual memory on standalone. On 2004 internally it can get so big that it gets more complicated to manage the cache than it's capable of doing quickly.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=XLmYsrQNeDQ:AiYB1FGjNHI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=XLmYsrQNeDQ:AiYB1FGjNHI:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=XLmYsrQNeDQ:AiYB1FGjNHI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=XLmYsrQNeDQ:AiYB1FGjNHI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=XLmYsrQNeDQ:AiYB1FGjNHI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=XLmYsrQNeDQ:AiYB1FGjNHI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=XLmYsrQNeDQ:AiYB1FGjNHI:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=XLmYsrQNeDQ:AiYB1FGjNHI:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/XLmYsrQNeDQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2008-10/4d-summit-qa-wrap-up/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2008-10/4d-summit-qa-wrap-up</feedburner:origLink></item>
		<item>
		<title>Turbocharging 4D v11 SQL</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/n4NzZ_0ncuk/turbocharging-4d-v11-sql</link>
		<comments>http://www.slicksurface.com/blog/2008-10/turbocharging-4d-v11-sql#comments</comments>
		<pubDate>Fri, 10 Oct 2008 23:48:52 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[4D]]></category>
		<category><![CDATA[4D Summit 2008]]></category>
		<category><![CDATA[4D-v11]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=234</guid>
		<description><![CDATA[[These are notes from 4D Summit 2008]
Presenters: Olivier Dechanels, Thibaud Arguillere
How the datafile is organized...
Each block in 4D's data file is 128 bytes.
Each block can only hold one item. An item may take more than one block and if so, they must be contiguous.
In the future they plan on having special data segments to store [...]]]></description>
			<content:encoded><![CDATA[<p>[These are notes from 4D Summit 2008]</p>
<p><em>Presenters: Olivier Dechanels, Thibaud Arguillere</em></p>
<p><img class="alignnone" style="margin: 5px 8px;" title="Olivier Deschanels giving a presentation at 4D Summit" src="http://www.slicksurface.com/blog/resources/2008/10/olivier-250x381.jpg" alt="Olivier Deschanels giving a presentation at 4D Summit" width="250" height="381" align="right" />How the datafile is organized...</p>
<p>Each block in 4D's data file is 128 bytes.</p>
<p>Each block can only hold one item. An item may take more than one block and if so, they must be contiguous.</p>
<p>In the future they plan on having special data segments to store large items. This will let you put certain items on different disks.</p>
<p>A record is made up of a Header, Values and a Micro-Structure. The micro-structure is the description of the record at the time the record was saved (in case it subsequently changes).</p>
<p>Header 32 bytes<br />
Values: Boolean: 1, Integer: 2, Longint: 4, Longint64/Date/Time: 8, Float: 7 + X Bytes, Alpha: 4+(2x nb chars), Blob/Picture/Text: 4<br />
Micro-structure: 8/field</p>
<p>Nulls don't take space in the data file other than in the micro-structure.</p>
<p>The micro-structure is really useful because you can change the structure of a table without having to worry about existing data. 4D will automatically translate and deal with data in a table that was stored in a different format.</p>
<p>While table numbers are never reused, field numbers are reused. This means that you do need to update customer data if you delete a field and add another that takes it's place. Otherwise you'll get the old data in the new field.</p>
<p>When data is read from the hard drive it reads the next bits of data into a buffer, but if the next thing it needs isn't in the buffer then it has to go looking for it. Hence, try to avoid fragmentation. The best way to do this is to avoid variable sized fields, and store text and blobs outside the record. The more you can have a fixed size record the less fragmentation, and the faster your app can read from disk. [Realize that if you need to access the text a lot this can work against you.]</p>
<p>They don't recommend using JPR's "airbag" strategy that adds variable amount of data to make all records the same size to avoid fragmentation. Better to just store variable size data outside the record. They're working on implementing an auto airbag to force records to take a fixed amount of space to avoid future fragmentation.</p>
<p>Realize that you may have free space in records. For example, a many to many joining table with just two longints. You can add denormalized data in there that can make operations faster without increasing the size of your data file.</p>
<p>They save the length of the record in the address table. If that doesn't match the actual length of the record they alert you there's a problem with your data file.</p>
<p>BLOBs, Pictures, Text fields - are stored outside the record, though v11.3 lets you set a size threshold for storing inside the record. In the record the ID of the external location is stored. On disk they have the same status as a record with address tables to help locate them. This will be optimized further in the future.</p>
<p><img class="alignnone" style="margin: 5px 8px;" src="http://www.slicksurface.com/blog/resources/2008/10/thibaud.jpg" alt="Thibaud Arguillere giving a presentation at 4D Summit" width="250" height="299" align="right" />In the future they're thinking of having indexes on formulas.</p>
<p>Indexes are somewhat costly. For a long integer index you're looking at 12 bytes per value plus the overhead of things like the header for the index and empty space in the index.</p>
<p>B-Tree indexes are structured on levels. Root = 128 keys, Level 1 = 128x128 = 16,384 keys, Level 2 = 16384 x 128 = 2,097,152 keys, etc. The number of access to find the record in the index depends on the number of levels - one access per level.</p>
<p>For ORDER BYs with multiple values have a composite index to speed them up.</p>
<p>In v2004 it would use the index if the selection had more than 9% of the records in the table, otherwise it would drop back to sequential for the QUERY or the ORDER BY. v11 is more intelligent and figures it out based on the number of disk accesses that are needed. This means a number of SET DATABASE PARAMETERs are now ignored.</p>
<p>Just because you create an index doesn't mean it will be used. Unused indexes slow down the database because it takes time to manage them and space to store them.</p>
<p>With cluster indexes each value has either a bit table or a long int array to remember the records that match that value. 4D decides which is more sufficient.</p>
<p>They're coming out with a 4DPop component (requires v11.3) that analyzes your data file and shows the storage details.</p>
<p>If you copy/paste pictures into 4D, v11 takes all the info you paste which may be considerably more than the picture itself. It's a good idea to CONVERT PICTURE($pict;"jpeg") to reduce the size of the images.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=n4NzZ_0ncuk:OE8nC6nOtHg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=n4NzZ_0ncuk:OE8nC6nOtHg:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=n4NzZ_0ncuk:OE8nC6nOtHg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=n4NzZ_0ncuk:OE8nC6nOtHg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=n4NzZ_0ncuk:OE8nC6nOtHg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=n4NzZ_0ncuk:OE8nC6nOtHg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=n4NzZ_0ncuk:OE8nC6nOtHg:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=n4NzZ_0ncuk:OE8nC6nOtHg:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/n4NzZ_0ncuk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2008-10/turbocharging-4d-v11-sql/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2008-10/turbocharging-4d-v11-sql</feedburner:origLink></item>
		<item>
		<title>4D v11 SQL Resources Architecture</title>
		<link>http://feedproxy.google.com/~r/slicksurface/~3/NP5ppdGhgNU/4d-v11-sql-resources-architecture</link>
		<comments>http://www.slicksurface.com/blog/2008-10/4d-v11-sql-resources-architecture#comments</comments>
		<pubDate>Fri, 10 Oct 2008 23:43:11 +0000</pubDate>
		<dc:creator>Jay Harper</dc:creator>
				<category><![CDATA[4D]]></category>
		<category><![CDATA[4D Summit 2008]]></category>
		<category><![CDATA[4D-v11]]></category>

		<guid isPermaLink="false">http://www.slicksurface.com/blog/?p=245</guid>
		<description><![CDATA[[These are notes from 4D Summit 2008.]
Presenter: Jesse Pina
Resources are now defined as files needed to translate an interface. Can be images or text. Everything is file based.
Converting from resource fork resources to file based resources

Strings -&#62; XLIF
Images -&#62; files
Constants -&#62; plugins
4D &#38; System - &#62; do not use

You can refer to xliff strings by [...]]]></description>
			<content:encoded><![CDATA[<p>[These are notes from 4D Summit 2008.]</p>
<p><em>Presenter: Jesse Pina</em></p>
<p>Resources are now defined as files needed to translate an interface. Can be images or text. Everything is file based.</p>
<p>Converting from resource fork resources to file based resources</p>
<ul>
<li>Strings -&gt; XLIF</li>
<li>Images -&gt; files</li>
<li>Constants -&gt; plugins</li>
<li>4D &amp; System - &gt; do not use</li>
</ul>
<p>You can refer to xliff strings by IDs or names...</p>
<ul>
<li>:15000,1</li>
<li> <img src='http://www.slicksurface.com/blog/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> liff:elementName</li>
</ul>
<p>You can override titles on objects on forms by specifying a resname on a xliff group that is the name of the table "[TableName]"</p>
<p>Which language gets loaded?</p>
<ol>
<li>First looks at OS language and if you have resources for that language, it uses that</li>
<li>If not, then uses language resources for the version of 4D that you're using</li>
<li>If not, then English</li>
<li>If not, then first valid lproj folder it finds</li>
</ol>
<p>If you want to override the language, then have multiple xliff files per language with each file having one language, and each language using different group IDs. Then use an interprocess variable for the group ID and refer to the resource by ID rather than name.</p>
<p>If you pull in a picture from a localized folder and then remove the directory from path it will use the file localized for the particular user.</p>
<p>Constants are moving to a plugin. They're providing "User Constants.bundle". It's still using the old resource fork.</p>
<p>If you make changes on the client side in client/server you need to use the resource explorer for it to replicate up to server.</p>
<p>As far as when things are replicated in client/server. You have an option to not push until next login (never), two minutes after the change (always), or if the client wants to accept the new resource (ask).</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/slicksurface?a=NP5ppdGhgNU:1iDpu-RoWa4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=NP5ppdGhgNU:1iDpu-RoWa4:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/slicksurface?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=NP5ppdGhgNU:1iDpu-RoWa4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=NP5ppdGhgNU:1iDpu-RoWa4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=NP5ppdGhgNU:1iDpu-RoWa4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=NP5ppdGhgNU:1iDpu-RoWa4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/slicksurface?a=NP5ppdGhgNU:1iDpu-RoWa4:wF9xT3WuBAs"><img src="http://feeds.feedburner.com/~ff/slicksurface?i=NP5ppdGhgNU:1iDpu-RoWa4:wF9xT3WuBAs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/slicksurface/~4/NP5ppdGhgNU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.slicksurface.com/blog/2008-10/4d-v11-sql-resources-architecture/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.slicksurface.com/blog/2008-10/4d-v11-sql-resources-architecture</feedburner:origLink></item>
	</channel>
</rss>
