Saturday, January 19, 2013

SEO (Search Engine Optimization) and Google

Google Search results are ordered by relevance, domain weight, and page weight.  Google's Search algorithm determines relevance based on the content of the web page.  Weight is determined by the historical performance of the page in Google's Search results based on the click-through rate of the page and domain.

Click-through:  How many times Users have clicked a link in the Google Search results?  More clicks = stronger weight for the page and for the domain.  Stronger domains and pages appear higher in the search results.


Here are my recommendations for driving strong SEO (sorted by importance):

1.  Business Descriptions in the Directory:  Our Clients have on average 1000 members.  That translates to a potential of 1000 pages of unique content if they can get their Members to write a business description.  Once achieved, they should always be pushing their Members to be adding to and updating their Descriptions.  

2.  Daily blog postings and comments:  Our Clients should use our News module to post daily content.  Site Visitors could be allowed to comment on the posting (We currently do not have this feature on our sites).  After 3 years of doing daily blog posts, our Clients could have 1000 pages of unique content.

3.  Lengthy custom content on many static pages:  Our Clients should shoot for the moon and try to reach 500+ pages of unique content.

4.  Pull in industry feeds: (We currently do not utilize this feature on our sites).  There are many sources to pull content from .  Our Clients could effortlessly pull in 1000 pages of replicated content by pulling in industry feeds.

5.  Attractive page titles:  When I perform a Google search, I typically scan the results and click on links that seem most relevant to me based on the title and description.  We should format our page Titles and content to generate attractive links on Google Search results.  Attractive links will be clicked more often.

6.  Google Search on our sites:  Once a User clicks through from Google, no matter how many pages the User navigates through the site, only one Google click-through is ever recorded.  So, how do you get more Google click-through?  Our Clients should use a Google Site Search on the site.  Every time a Google Site search result is clicked, Google records another click-through.

7.  Keywords to Google Site Search:  Similar to the "Google Search on our sites" SEO recommendation, above, Google click-through can be driven off keywords that link to a Google Site Search.  If a site Visitor clicks the keyword, they would receive a list of relevant Google results for pages on the site.  If they click on a result, a Google click-through is recorded.

8.  Pull in Social Media Feeds:  There is a small boost if we pull in our Client's Social Media feeds and post the content on their site.  Imagine the boost if we also pulled in their Members Social Media content (We currently do not have this feature on our sites).  It is possible to effortlessly pull in 1000 pages of relevant, timely, replicated content from our Client's Members.

9.  Include Non-Members in the Directory:  We have, yet, to have one of our Clients take the leap and include Non-Member Organizations in their Business Directory.  Non-Members could have a very basic Listing with no contact information.  It is possible to add 10,000 lines of unique content to our Client's sites.

10.  API for Content Writers:  (We currently do not have this feature on our sites)  We may be able to create an API for our Clients where they could license publishing writes to local content writers (newspaper, tourism dept., economic development, political action, etc.).  Our sites could gain 1000s of pages of content for free.


Note:  I did not put Meta keyword and description on this list.  Here is why:
Many people give way too much credit for what meta keywords and description can do for SEO.  I do not believe Meta keywords and description have any real pull with modern search engines.  I believe the search engines are more concerned with content.  Google pushes for meta description for the sole purpose of adding relevancy to the links in their Search results.  They will sometimes use the Meta description as the link description (below the link title) to make the link more attractive.  Meta descriptions are not Google facing, but rather Google End User facing.


Summary
Our Clients sites could potentially have 7000 pages of strong content.  From my experience, our average site typically has about 150 pages of good content and 1000 pages of poor content.  Our best sites have about 1000 pages of good content and 1000 pages of poor content.  Based on these findings, I'd estimate our sites are operating between 2% and 14% potential Search Engine Optimization.

Our sites could drive Google click-through better.  

Our page titles and descriptions could be formatted better.

Please feel free to try to outdo my list with your own SEO suggestions.

Tuesday, November 6, 2012

Seach Engines Causing Load Problems on Web Server


Search engines need to crawl websites regularly to index new content and check for changes to existing content.  The frequency search engine bots spend on a website can cause the server to experience load problems. Most major search engines allow the ability to slow the crawl rate.
Small websites which do not update their content regularly will likely never need to slow the crawl rate.  Bots will adjust the crawl rate to an appropriate frequency based on the content they find.
For large websites with many pages updated more frequently, search engines may attempt to visit the site often and crawl deeper.
The crawl-rate can be set inside of the robots.txt file as shown (in seconds):
User-agent: *Crawl-delay: 10

But, wait, Google doesn't support this.  You have to adjust your settings in Google Webmaster Tools.  And, they have the nerve to say they can ignore this setting whenever they want and do it anyway...

Saturday, September 1, 2012

230 Color Palette for Telerik radEditor radColorPicker

<colors> <!-- row 1 --> <color value="#000000"/> <color value="#111111"/> <color value="#00CC00"/> <color value="#336600"/> <color value="#660000"/> <color value="#66CC00"/> <color value="#996600"/> <color value="#CC0000"/> <color value="#CCCC00"/> <color value="#FF6600"/> <!-- row 2 --> <color value="#111111"/> <color value="#000066"/> <color value="#00CC66"/> <color value="#336666"/> <color value="#660066"/> <color value="#66CC66"/> <color value="#996666"/> <color value="#CC0066"/> <color value="#CCCC66"/> <color value="#FF6666"/> <!-- row 3 --> <color value="#222222"/> <color value="#000099"/> <color value="#00CC99"/> <color value="#336699"/> <color value="#660099"/> <color value="#66CC99"/> <color value="#996699"/> <color value="#CC0099"/> <color value="#CCCC99"/> <color value="#FF6699"/> <!-- row 4 --> <color value="#333333"/> <color value="#0000CC"/> <color value="#00CCCC"/> <color value="#3366CC"/> <color value="#6600CC"/> <color value="#66CCCC"/> <color value="#9966CC"/> <color value="#CC00CC"/> <color value="#CCCCCC"/> <color value="#FF66CC"/> <!-- row 5 --> <color value="#444444"/> <color value="#0000FF"/> <color value="#00CCFF"/> <color value="#3366FF"/> <color value="#6600FF"/> <color value="#66CCFF"/> <color value="#9966FF"/> <color value="#CC00FF"/> <color value="#CCCCFF"/> <color value="#FF66FF"/> <!-- row 6 --> <color value="#555555"/> <color value="#003300"/> <color value="#00FF00"/> <color value="#339900"/> <color value="#663300"/> <color value="#66FF00"/> <color value="#999900"/> <color value="#CC3300"/> <color value="#CCFF00"/> <color value="#FF9900"/> <!-- row 7 --> <color value="#666666"/> <color value="#003333"/> <color value="#00FF33"/> <color value="#339933"/> <color value="#663333"/> <color value="#66FF33"/> <color value="#999933"/> <color value="#CC3333"/> <color value="#CCFF33"/> <color value="#FF9933"/> <!-- row 8 --> <color value="#777777"/> <color value="#003366"/> <color value="#00FF66"/> <color value="#339966"/> <color value="#663366"/> <color value="#66FF66"/> <color value="#999966"/> <color value="#CC3366"/> <color value="#CCFF66"/> <color value="#FF9966"/> <!-- row 9 --> <color value="#808080"/> <color value="#003399"/> <color value="#00FF99"/> <color value="#339999"/> <color value="#663399"/> <color value="#66FF99"/> <color value="#999999"/> <color value="#CC3399"/> <color value="#CCFF99"/> <color value="#FF9999"/> <!-- row 10 --> <color value="#888888"/> <color value="#0033CC"/> <color value="#00FFCC"/> <color value="#3399CC"/> <color value="#6633CC"/> <color value="#66FFCC"/> <color value="#9999CC"/> <color value="#CC33CC"/> <color value="#CCFFCC"/> <color value="#FF99CC"/> <!-- row 11 --> <color value="#909090"/> <color value="#0033FF"/> <color value="#00FFFF"/> <color value="#3399FF"/> <color value="#6633FF"/> <color value="#66FFFF"/> <color value="#9999FF"/> <color value="#CC33FF"/> <color value="#CCFFFF"/> <color value="#FF99FF"/> <!-- row 12 --> <color value="#949494"/> <color value="#006600"/> <color value="#330000"/> <color value="#33CC00"/> <color value="#666600"/> <color value="#990000"/> <color value="#99CC00"/> <color value="#CC6600"/> <color value="#FF0000"/> <color value="#FFCC00"/> <!-- row 13 --> <color value="#999999"/> <color value="#006633"/> <color value="#330033"/> <color value="#33CC33"/> <color value="#666633"/> <color value="#990033"/> <color value="#99CC33"/> <color value="#CC6633"/> <color value="#FF0033"/> <color value="#FFCC33"/> <!-- row 14 --> <color value="#9c9c9c"/> <color value="#006666"/> <color value="#330066"/> <color value="#33CC66"/> <color value="#666666"/> <color value="#990066"/> <color value="#99CC66"/> <color value="#CC6666"/> <color value="#FF0066"/> <color value="#FFCC66"/> <!-- row 15 --> <color value="#aaaaaa"/> <color value="#006699"/> <color value="#330099"/> <color value="#33CC99"/> <color value="#666699"/> <color value="#990099"/> <color value="#99CC99"/> <color value="#CC6699"/> <color value="#FF0099"/> <color value="#FFCC99"/> <!-- row 16 --> <color value="#B1B1B1"/> <color value="#0066CC"/> <color value="#3300CC"/> <color value="#33CCCC"/> <color value="#6666CC"/> <color value="#9900CC"/> <color value="#99CCCC"/> <color value="#CC66CC"/> <color value="#FF00CC"/> <color value="#FFCCCC"/> <!-- row 17 --> <color value="#B8B8B8"/> <color value="#0066FF"/> <color value="#3300FF"/> <color value="#33CCFF"/> <color value="#6666FF"/> <color value="#9900FF"/> <color value="#99CCFF"/> <color value="#CC66FF"/> <color value="#FF00FF"/> <color value="#FFCCFF"/> <!-- row 18 --> <color value="#BFBFBF"/> <color value="#009900"/> <color value="#333300"/> <color value="#33FF00"/> <color value="#669900"/> <color value="#993300"/> <color value="#99FF00"/> <color value="#CC9900"/> <color value="#FF3300"/> <color value="#FFFF00"/> <!-- row 19--> <color value="#C6C6C6"/> <color value="#009933"/> <color value="#333333"/> <color value="#33FF33"/> <color value="#669933"/> <color value="#993333"/> <color value="#99FF33"/> <color value="#CC9933"/> <color value="#FF3333"/> <color value="#FFFF33"/> <!-- row 20 --> <color value="#CDCDCD"/> <color value="#009966"/> <color value="#333366"/> <color value="#33FF66"/> <color value="#669966"/> <color value="#993366"/> <color value="#99FF66"/> <color value="#CC9966"/> <color value="#FF3366"/> <color value="#FFFF66"/> <!-- row 21 --> <color value="#D4D4D4"/> <color value="#009999"/> <color value="#333399"/> <color value="#33FF99"/> <color value="#669999"/> <color value="#993399"/> <color value="#99FF99"/> <color value="#CC9999"/> <color value="#FF3399"/> <color value="#FFFF99"/> <!-- row 22 --> <color value="#DBDBDB"/> <color value="#0099CC"/> <color value="#3333CC"/> <color value="#33FFCC"/> <color value="#6699CC"/> <color value="#9933CC"/> <color value="#99FFCC"/> <color value="#CC99CC"/> <color value="#FF33CC"/> <color value="#FFFFCC"/> <!-- row 23 --> <color value="#E9E9E9"/> <color value="#0099FF"/> <color value="#3333FF"/> <color value="#33FFFF"/> <color value="#6699FF"/> <color value="#9933FF"/> <color value="#99FFFF"/> <color value="#CC99FF"/> <color value="#FF33FF"/> <color value="#ffffff"/> </colors>

Tuesday, March 20, 2012

VB.NET - Show Hidden Form Elements with a Keyboard Shortcut

I created a keyboard shortcut to show form elements that aren't quite production ready:

Private Sub showHiddenElementsByKeyboardCombo(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
If (e.KeyCode = Keys.H AndAlso e.Modifiers = Keys.Control AndAlso e.Modifiers = Keys.Alt) Then
MsgBox("The keyboard shortcut you used is about to allow you to see hidden features which have not been fully tested. If this was not your intention, close the tab and re-open it.")
dropDown1.Visible = True
dropDown2.Visible = True
dropDown3.Visible = True
End If
End Sub

Tuesday, February 21, 2012

Google Maps V3 With Multiple Markers and Multiple InfoWindows

For anyone looking for the simple answer to creating a Google Maps Version 3 API map with multiple markers and multiple info windows, here is my simple and dependable solution:


        var locationsToMap = [
            [39.638547, -85.952911, "Southeast Corner"],
            [39.914990, -85.957193, "Northeast Corner"],
            [39.922966, -86.325456, "Northwest Corner"],
            [39.633365, -86.325456, "Southwest Corner"]
        ];

        function addGeoLocationsToMap() {
            var myOptions = {
                center: new google.maps.LatLng(getLatOfMapCenter(), getLongOfMapCenter()),
                zoom: getMapZoomLevel(),
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            // "map_canvas" is the div container for the map
            map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

            var inforwindow = null;

            for (var i = 0; i < locationsToMap.length; i++) {
                //listingLatitude[x] and listinglongitude[x] are arrays holding the latitude and longitude for the marker
                if ((locationsToMap[i][0] != 0) && (locationsToMap[i][1] != 0)) {
                    //we are using an "eval(); expression to dynamically write new javascript in each loop
                    eval("var marker" + i + " = new google.maps.Marker({position: new google.maps.LatLng(" + locationsToMap[i][0] + ", " + locationsToMap[i][1] + "),map: map});");
                    //locationsToMap[x] is an array holding the html for the infowindows
                    eval("google.maps.event.addListener(marker" + i + ", 'click', function() {infowindow = new google.maps.InfoWindow({content: locationsToMap[" + i + "][2] + '
'});infowindow.open(map,marker" + i + ");} );");
                }
            }
        }

        function getLatOfMapCenter() {
            return 39.773595;
        }

        function getLongOfMapCenter() {
            return -86.150399;
        }

        function getMapZoomLevel() {
            return 10;
        }

Saturday, January 28, 2012

XAML: Changing a Style on MouseOver of the Parent Item

Sometimes, you want a Mouse Over event to trigger a style change on some or all the items within a container.

Changing Image style when a Mouse moves over a custom parent container (WC_MenuItem). Any type of container or Panel can be substituted for the custom type I've used.

<Image x:Name="imgHelpLink" Source="pack://application:,,,/Weblink_WPF;component/Images/Help.png" Cursor="Hand" Grid.Column="1" Width="16" Height="16" Margin="0,0,0,0" ToolTip="Click to view the Knowledgebase article on this report" HorizontalAlignment="Right" >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Opacity" Value="0" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type weblink_controls:WC_MenuItem}},Path=IsMouseOver}" Value="True">
<Setter Property="Opacity" Value="1" />
</DataTrigger>
<!--<DataTrigger Binding="{Binding Path=HelpLink.Length}" Value="0">
<Setter Property="Opacity" Value="0.3"/>
</DataTrigger>-->
</Style.Triggers>
</Style>
</Image.Style>
</Image>

Serializing and DeSerializing Objects as XML in VB.NET

It was unbelievably difficult to find a working example where the XML could come from a web server on a different domain. So, I guess I will share with the world how I managed to make it work.

Serialize List of Objects to XML
(Web Server)

Dim xml As String = ""
Dim mstr_XmlFilePath As String = "/myFolder/myFile.xml"
Dim mstr_ServerXmlFilePath As String = Server.mapPath(mstr_XmlFilePath)
Dim obj_objMyObject As New objMyObject
Dim lst_objMyObject As List(Of objMyObject) = [[***populate object***]]

Try

Dim ser As XmlSerializer
ser = New XmlSerializer(GetType(System.Collections.Generic.List(Of objMyObject)))
Dim memStream As New MemoryStream
Dim xmlWriter As New XmlTextWriter(memStream, Encoding.UTF8)
xmlWriter.Namespaces = True
ser.Serialize(xmlWriter, lst_objMyObject)
xmlWriter.Close()
memStream.Close()

xml = Encoding.UTF8.GetString(memStream.GetBuffer())
xml = xml.Substring(xml.IndexOf(Convert.ToChar(60)))
xml = xml.Substring(0, (xml.LastIndexOf(Convert.ToChar(62)) + 1))

My.Computer.FileSystem.WriteAllText(XmlFilePath, xml, False)

Catch ex As Exception
Throw New Exception("Error calling ToXML. " & ex.GetBaseException.ToString)
End Try


DeSerialize List of Objects from XML (Client or Cross-Domain Web Server)

str_XmlFullFilePath = "myURL" + mstr_XmlFilePath
Dim objListFromXml As New List(Of objMyObject)
Try

Dim reader As System.Xml.XmlReader
reader = System.Xml.XmlReader.Create(str_XmlFullFilePath)

Dim mySerializer As XmlSerializer = New XmlSerializer(GetType(System.Collections.Generic.List(Of objMyObject)))
objListFromXml = CType(mySerializer.Deserialize(reader), System.Collections.Generic.List(Of objMyObject))

Catch
'don't do anything. If error occurs, return an empty object
End Try

I may have some typos above. I replaced all my variables with more generic ones.