====== Tellmaps: URL, SEO ======
This document proposes new URL format for tellmaps to resolve these issues:
* for the user, to have a representative URL of current situation in the location bar
* for the user, to allow navigation using browser's back / forward buttons
* for search engines, to serve static content to be parsed when using dynamic URL's
===== URL format =====
We propose a shebang syntax, which is backward-compatible with most browsers and uses a hash-trick to allow dynamic changes of the URL. It is also directly supported by search engines such as Google.
Shebang syntax is defined as follows:
http://server.name/#!/path/to/web/feature?param1=value¶m2=value#local-hash
which can be decomposed to three major parts:
* a **path component**, ''/path/to/web/feature'' - this is the main path of given server resouce, in case of tellmaps, an address of a particular map
* a **param set**, ''?param1=value¶m2=value'' - this is a GET string with dynamic parameters such as filtering, country targetting, view change
* a **local hash**, ''#local-hash'' - this is used as a normal hash, i.e. to scroll to a given part of document (top / bottom etc).
[Implementation details] code to retriveve params from hash part: https://gist.github.com/miohtama/1570295
===== URLs for Tellmaps =====
We propose to use the above parts this way:
==== Path component ====
Should contain a path to resource. We propose:
* for site content: directly name of the page, such as ''/contact'', ''/about us'' etc.
* for tellmaps: identifier of tellmap, tellmap ID or name. Arbitrarily, edition name. Examples: ''/tellmap/oil-consupmtion'' or with edition, ''/tellmap/angola/human-resouce-index''. The identifiers should be URL-parsable strings in lower case, or less preferably ID (numeric). The nesting of edition/map is better for SEO purposes.
* for country/province profiles: should be very simmilar but using different prefix than ''tellmap'' such as ''/province/{edition_name}/{province_name}''
* ...some more?
The general rule of thumb is: if we have a content we want to serve to search engine as a static document, it should have an unique path component.
==== Param set ====
Should contain all kinds of data we don't need a SEO representation of. Such as filtering, pagination, views. Due to it's nature it should be in a format of ''property_name=property_value''. We shall have a way on how to define defaults for these values if ommited in the application.
Examples of params (names - values):
* ''legend'' - numeric
* ''date'' - year
* ''focus'' - part of map to focus on, string
* ''carthogram'' - true / false
Advantages of param set over path set (such as ''/tellmap/WDAWORLD01/date/1974/focus/BRA/cartogram/true''):
* params are simpler to parse / assemble, it's much harder to make a mistake as would be in the above if we remove one part of component, such as ''date''
* we can distinguish between what is a path to resource, and what is only a different way to display it
Params will be parsed rather simply - we won't support arrays.
==== local hash ====
Will only be used if we need to scroll to some element ID. Because we don't have a way to do this if using shebang syntax directly, we can parse the additional ''#'' at the end of a path and programatically scroll to given DOM ID element. This will enable scroll to top / certain element.
===== Javascript implementation =====
/**
* revised version with one settings object and multiple callback definitions
* @param settings - collection {}, specify these properties:
* - path - string - define a path component with possible :variable notation
* - onPathSet - function(variables) - pass in a callback to be called whenever a path changes
* - @param variables - collection of passed :variable values
* in format { variable_name: variable_value }
* - onPathOut - function() - pass in a callback to as destructor function
* - is called whenever path components change from this path
* - onParamsChange - function(params) - pass in a callback to be called whenever a param string changes
* - @param params - collections of passed GET params
* in format { param_name: param_value }
* - defaultParams - collection - define an array of default GET values - they automatically pre-fill the
* params in onParamsChange callback if not provided from GET
* - onHashChange - function(local_hash) - pass in a callback to be called whenever a local hash part changes
* - @param local_hash - provides new value of local_hash
* - @default if not defined, will perform a scroll to page top / element of ID #local_hash,
* as standard hash does
* - debug - boolean - provide console.log outputs on various operations of this registerURI block
* @return none
*
* notes:
* - all callbacks have "this" set which can access the following:
* getHash(), getParams(), getParamString(), getPath()
* please do not use their "set" counterparts directly.
**/
function registerUri( settings ) {
...
/**
* Register a callback to be executed on URI parse fail
* @param callback - a function in the form of function(current_uri, error_message)
* current_uri is the processed shebang that failed
* error_message does show a messages the class outputted on fail
* function will be called on URI parse failed
* @return none
*
* notes:
* - callback has "this" set which can access the following:
* getHash(), getParams(), getParamString(), getPath()
* please do not use their "set" counterparts directly.
**/
function onUriFail( callback ) {
...
/**
* Get proper URI string to be used in parts of the app
* @param path - string, path component part
* @param get_params - get param collection in the form of { param_name : param_value }
* @param local_hash - string, local hash part
* @return string final string
**/
function getUriString( path, get_params, local_hash ) {
...
This solution has these advantages:
* destructor on path component change - can be used to free memory-intensive resouces, kill dialogs etc.
* separate GET params / path component / local hash change callbacks - better, isolated events. The event order is as follows:
(change a path component) -> trigger onPathSet -> trigger onParamChange -> trigger onHashChange
(change a params part) -> trigger onParamChange only
(change a local hash part) -> trigger onHashChange only
===== Server-side implementation =====
==== Old URI redirection ====
Should perform a redirection from old to new format using rules described above. Should be done server-side with R=301 redirects.
==== SEO - support ====
Shebang format has an advantage in that it allows search engines to crawl them. When it notices the shebang format such as ''http://example.com/#!/some/path'', it automatically requests ''http://example.com?_escaped_fragment=/some/path'' and this can be processed using the server and serving the search engine with custom SEO-ready content version of a given resource.
**This will need much more through-thinking** but the URL part is a good start.