<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://developer.directededge.com/index.php?feed=atom&amp;namespace=0&amp;title=Special%3ANewPages</id>
		<title>the Directed Edge Developer Base - New pages [en]</title>
		<link rel="self" type="application/atom+xml" href="https://developer.directededge.com/index.php?feed=atom&amp;namespace=0&amp;title=Special%3ANewPages"/>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Special:NewPages"/>
		<updated>2026-04-21T06:12:03Z</updated>
		<subtitle>From the Directed Edge Developer Base</subtitle>
		<generator>MediaWiki 1.28.2</generator>

	<entry>
		<id>https://developer.directededge.com/article/Recommendation_parameters</id>
		<title>Recommendation parameters</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Recommendation_parameters"/>
				<updated>2014-01-03T21:59:54Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;List&amp;#039;&amp;#039; parameters are just a comma separated list of strings, defaulting to an empty list.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Type&lt;br /&gt;
! Name&lt;br /&gt;
! Default&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| float&lt;br /&gt;
| &amp;#039;&amp;#039;type&amp;#039;&amp;#039;Weight&lt;br /&gt;
| &lt;br /&gt;
| Specifies the relative weights of various link types.  See [[REST API#typeWeight|the description in our REST docs]]&lt;br /&gt;
|-&lt;br /&gt;
| list&lt;br /&gt;
| tags&lt;br /&gt;
| &lt;br /&gt;
| Only include items which possess the specified tags&lt;br /&gt;
|-&lt;br /&gt;
| list&lt;br /&gt;
| excludedTags&lt;br /&gt;
| &lt;br /&gt;
| Exclude items which possess the specified tags&lt;br /&gt;
|-&lt;br /&gt;
| list&lt;br /&gt;
| exclude&lt;br /&gt;
| &lt;br /&gt;
| Exclude the items with the given IDs&lt;br /&gt;
|-&lt;br /&gt;
| list&lt;br /&gt;
| items&lt;br /&gt;
| &lt;br /&gt;
| For a database-related request (i.e. basket request), specifies the list of items to find related items to; for a normal database GET request, specifies which items should be returned (useful for getting information about a number of items at once)&lt;br /&gt;
|-&lt;br /&gt;
| boolean&lt;br /&gt;
| showReferences&lt;br /&gt;
| false&lt;br /&gt;
| Show the &amp;quot;references&amp;quot; (back-links) for an item GET&lt;br /&gt;
|-&lt;br /&gt;
| list&lt;br /&gt;
| ignore&lt;br /&gt;
| &lt;br /&gt;
| Do not include or factor into ranking the listed IDs&lt;br /&gt;
|-&lt;br /&gt;
| boolean&lt;br /&gt;
| excludeLinked&lt;br /&gt;
| false (recommended) / true (related)&lt;br /&gt;
| Don&amp;#039;t include the items directly linked from the query item (i.e. products already purchased by a customer)&lt;br /&gt;
|-&lt;br /&gt;
| int&lt;br /&gt;
| maxResults&lt;br /&gt;
| 20&lt;br /&gt;
| The maximum number of recommended entries to return&lt;br /&gt;
|-&lt;br /&gt;
| boolean&lt;br /&gt;
| includeProperties&lt;br /&gt;
| false&lt;br /&gt;
| Include the properties for the item as XML attributes in a related or recommended query&lt;br /&gt;
|-&lt;br /&gt;
| boolean&lt;br /&gt;
| includeTags&lt;br /&gt;
| false&lt;br /&gt;
| Include the tags for the item as an XML attribute (comma separated) in a related or recommended query&lt;br /&gt;
|-&lt;br /&gt;
| list&lt;br /&gt;
| include&lt;br /&gt;
| &lt;br /&gt;
| Hand-pick the listed IDs for inclusion in a recommended or related query&lt;br /&gt;
|-&lt;br /&gt;
| string&lt;br /&gt;
| tagOperation&lt;br /&gt;
| OR&lt;br /&gt;
| Specifies whether the list of tags specified in &amp;quot;tags&amp;quot; should be evaluated using a logical &amp;quot;or&amp;quot; or logical &amp;quot;and&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| enum [ add, subtract, replace ]&lt;br /&gt;
| updateMethod&lt;br /&gt;
| replace&lt;br /&gt;
| Specifies the behavior POSTed updates to items&lt;br /&gt;
|-&lt;br /&gt;
| list&lt;br /&gt;
| itemsToRank&lt;br /&gt;
| &lt;br /&gt;
| Ranks a specific set of items using the &amp;quot;related&amp;quot; method&lt;br /&gt;
|-&lt;br /&gt;
| float (0 .. 1.0)&lt;br /&gt;
| popularity&lt;br /&gt;
| -1.0 (automatic)&lt;br /&gt;
| Skews results towards more niche or popular items&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Shopify_Liquid_Examples</id>
		<title>Shopify Liquid Examples</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Shopify_Liquid_Examples"/>
				<updated>2013-10-10T17:43:17Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here are a few examples of custom styles that can be used in the Directed Edge custom style engine for Shopify.&lt;br /&gt;
&lt;br /&gt;
Note that in general you&amp;#039;ll probably want to incorporate the CSS that&amp;#039;s here into your site&amp;#039;s main CSS file(s), but it&amp;#039;s included here to make the examples more complete and usable out of the box.&lt;br /&gt;
&lt;br /&gt;
Also see our [[Shopify Liquid|variable reference]].&lt;br /&gt;
&lt;br /&gt;
== Basic Example (Plain-text output) ==&lt;br /&gt;
This basic example demonstrates iterating through different recommendation types (called &amp;lt;tt&amp;gt;groups&amp;lt;/tt&amp;gt;) and listing a maximum of five recommended products per group in a nested iteration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;shopify-custom-style&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
{% for group in groups %}&lt;br /&gt;
&amp;lt;h3&amp;gt;{{ group.label }}&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  {% if group.bundle %}&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{{ bundle.buy_link }}&amp;quot;&amp;gt;{{ bundle.text }}&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  {% else %}&lt;br /&gt;
    {% for product in group.products limit:5 %}&lt;br /&gt;
    &amp;lt;li&amp;gt;&lt;br /&gt;
      &amp;lt;a href=&amp;quot;{{ product.url }}&amp;quot;&amp;gt;{{ product.title }}&amp;lt;/a&amp;gt;&lt;br /&gt;
      for {{ product.price | money }}&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    {% endfor %}&lt;br /&gt;
  {% endif %}&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
{% endfor %}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;tt&amp;gt;{% if group.bundle %}…{% else %}…{% endif %}&amp;lt;/tt&amp;gt; block we handle the special case of a group being a bundle. In this case we want to have a different link &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;{{ bundle.buy_link }}&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; that adds the bundled products to the basket. Also we want to show a message &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;{{ bundle.buy_text }}&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; that contains the price of the whole bundle. For more information on bundles see the [[Shopify_Liquid|Variable Reference]].&lt;br /&gt;
&lt;br /&gt;
== Default ==&lt;br /&gt;
&lt;br /&gt;
This is a simple, but usable style that&amp;#039;s shown by default when you switch to the custom layout mode.  It features a simple list of up to 5 products per recommendations type, plus bundles.  Products are shown with a simple 5 pixel border.  This is a responsive style.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;shopify-custom-style&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;recommendations&amp;quot;&amp;gt;&lt;br /&gt;
  {% for group in groups %}&lt;br /&gt;
    &amp;lt;div class=&amp;quot;recommendations-group&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;h3&amp;gt;{{ group.label }}&amp;lt;/h3&amp;gt;&lt;br /&gt;
      {% if group.bundle %}&lt;br /&gt;
        &amp;lt;div id=&amp;quot;bundle&amp;quot;&amp;gt;&lt;br /&gt;
          &amp;lt;img class=&amp;quot;bundle-first&amp;quot;&lt;br /&gt;
               src=&amp;quot;{{ group.products.first.featured_image | product_img_url: &amp;#039;compact&amp;#039; }}&amp;quot; /&amp;gt;&lt;br /&gt;
          &amp;lt;span class=&amp;quot;bundle-plus&amp;quot;&amp;gt;+&amp;lt;/span&amp;gt;&lt;br /&gt;
          &amp;lt;img class=&amp;quot;bundle-last&amp;quot;&lt;br /&gt;
               src=&amp;quot;{{ group.products.last.featured_image | product_img_url: &amp;#039;compact&amp;#039; }}&amp;quot; /&amp;gt;&lt;br /&gt;
          &amp;lt;span class=&amp;quot;bundle-label&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;{{ bundle.buy_link }}&amp;quot;&amp;gt;{{ bundle.text }}&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
      {% else %}&lt;br /&gt;
        {% for product in group.products limit:5 %}&lt;br /&gt;
          &amp;lt;div class=&amp;quot;recommendations-product&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;recommendations-product-image&amp;quot;&amp;gt;&lt;br /&gt;
              &amp;lt;a href=&amp;quot;{{ product.url }}&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;img src=&amp;quot;{{ product.featured_image |  product_img_url: &amp;#039;compact&amp;#039; }}&amp;quot;&amp;gt;&lt;br /&gt;
              &amp;lt;/a&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;title&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;{{ product.url }}&amp;quot;&amp;gt;{{ product.title }}&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;price&amp;quot;&amp;gt;{{ product.price | money }}&amp;lt;/div&amp;gt;&lt;br /&gt;
          &amp;lt;/div&amp;gt;&lt;br /&gt;
        {% endfor %}&lt;br /&gt;
      {% endif %}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  {% endfor %}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;style type=&amp;quot;text/css&amp;quot; media=&amp;quot;screen&amp;quot;&amp;gt;&lt;br /&gt;
#recommendations h3, .recommendations-group {&lt;br /&gt;
    padding: 0.5em 0;&lt;br /&gt;
    clear: both;&lt;br /&gt;
}&lt;br /&gt;
.recommendations-group .recommendations-product {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    vertical-align: top;&lt;br /&gt;
    width: 200px;&lt;br /&gt;
    padding-bottom: 0.5em;&lt;br /&gt;
}&lt;br /&gt;
.recommendations-group .recommendations-product div {&lt;br /&gt;
    margin: 0.5em 0;&lt;br /&gt;
}&lt;br /&gt;
.recommendations-group .recommendations-product img, #bundle img {&lt;br /&gt;
    border: 10px solid #f6f6f6;&lt;br /&gt;
}&lt;br /&gt;
.recommendations-product-image {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    bottom: 0px;&lt;br /&gt;
    height: 180px;&lt;br /&gt;
}&lt;br /&gt;
.recommendations-product-image img {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 0px;&lt;br /&gt;
}&lt;br /&gt;
#bundle &amp;gt; *{&lt;br /&gt;
    vertical-align: middle;&lt;br /&gt;
    margin-bottom: 1em;&lt;br /&gt;
}&lt;br /&gt;
#bundle .bundle-plus {&lt;br /&gt;
    font-size: 3em;&lt;br /&gt;
}&lt;br /&gt;
#bundle .bundle-label {&lt;br /&gt;
    font-size: 1.5em;&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
#bundle .bundle-last {&lt;br /&gt;
    margin-right: 0.5em;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Stylized recommendations with CSS 3 animations ==&lt;br /&gt;
&lt;br /&gt;
The next example shows the real powers of customized templates in Directed Edge for Shopify. This example shows only the product images of the recommended products. If you hover over one of them a neat animation will enlarge that particular item and reveal a product&amp;#039;s title, price and also the original price if the product is on sale.&lt;br /&gt;
As you will see CSS-code can be directly embedded into the liquid template.&lt;br /&gt;
&lt;br /&gt;
Note hover that: &amp;#039;&amp;#039;&amp;#039;JavaScript code will be stripped out before rendering&amp;#039;&amp;#039;&amp;#039;.&amp;lt;br&amp;gt;&lt;br /&gt;
If you need to use JavaScript it has to be embedded in the Shopify templates. You can set a callback using &amp;lt;tt&amp;gt;{% assign directed-edge-callback = &amp;#039;myJsFunction&amp;#039; %}&amp;lt;/tt&amp;gt; before including the &amp;lt;tt&amp;gt;{% include &amp;#039;directed-edge&amp;#039; %}&amp;lt;/tt&amp;gt; snippet. Since you can set element ids and classes as you need you will be able to easily manipulate the elements later.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;shopify-custom-style&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&lt;br /&gt;
.recommendations-label {&lt;br /&gt;
  font-family: Arial, sans-serif;&lt;br /&gt;
  font-size: 2em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.recommendation-group {&lt;br /&gt;
  float: left;&lt;br /&gt;
  display: block;&lt;br /&gt;
  clear: both;&lt;br /&gt;
  padding: 5px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.recommended-item {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  float: left;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  height: 102px;&lt;br /&gt;
  padding: 3px;&lt;br /&gt;
  margin: 3px;&lt;br /&gt;
  border: 1px solid #ddd;&lt;br /&gt;
  border-radius: 3px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.bundle-plus {&lt;br /&gt;
  display: inline-block;&lt;br /&gt;
  float: left;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  height: 102px;&lt;br /&gt;
  padding: 3px;&lt;br /&gt;
  margin: 3px;&lt;br /&gt;
  font-family: Arial, sans-serif;&lt;br /&gt;
  font-size: 2em;&lt;br /&gt;
  line-height:4em;&lt;br /&gt;
  vertical-align: middle;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.recommended-image-container {&lt;br /&gt;
  float: left;&lt;br /&gt;
  width: 102px;&lt;br /&gt;
  line-height: 100px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.recommended-image-container img {&lt;br /&gt;
  vertical-align: top;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.recommended-details {&lt;br /&gt;
  width: 1px;&lt;br /&gt;
  height: 102px;&lt;br /&gt;
  float: left;&lt;br /&gt;
  overflow: clip;&lt;br /&gt;
  text-align: left;&lt;br /&gt;
  transition: width 0.2s;&lt;br /&gt;
  -webkit-transition: width 0.2s; /* Safari, Chrome */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.recommended-item:hover .recommended-details {&lt;br /&gt;
  width: 120px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.rtitle, .rprice {&lt;br /&gt;
  margin-left: 1px;&lt;br /&gt;
  text-align: left;&lt;br /&gt;
  overflow: hidden;&lt;br /&gt;
  white-space: nowrap;&lt;br /&gt;
  text-overflow: ellipsis;&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
.sale-price {&lt;br /&gt;
  text-decoration: line-through;&lt;br /&gt;
}    &lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;recommendations&amp;quot;&amp;gt;&lt;br /&gt;
{% for group in groups %}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;recommendation-group&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;span class=&amp;quot;recommendations-label&amp;quot;&amp;gt;{{ group.label }}&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
      {% for product in group.products %}&lt;br /&gt;
      &amp;lt;a href=&amp;quot;{{ product.url }}&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;recommended-item&amp;quot;&amp;gt;&lt;br /&gt;
          &amp;lt;div class=&amp;quot;recommended-image-container&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;img src=&amp;quot;{{ product.featured_image | product_img_url: &amp;#039;small&amp;#039; }}&amp;quot; /&amp;gt;&lt;br /&gt;
          &amp;lt;/div&amp;gt;&lt;br /&gt;
          &amp;lt;div class=&amp;quot;recommended-details&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;rtitle&amp;quot;&amp;gt;&lt;br /&gt;
              {{ product.title }}&amp;lt;br/&amp;gt;&lt;br /&gt;
              {% if product.compare_at_price_min &amp;gt; product.price_min %}&lt;br /&gt;
              &amp;lt;span class=&amp;quot;sale-price&amp;quot;&amp;gt;{{ product.compare_at_price_min | money }}&amp;lt;/span&amp;gt;&lt;br /&gt;
              {% endif %}&lt;br /&gt;
              {{ product.price | money }}&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
          &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;/a&amp;gt;&lt;br /&gt;
      {% if group.bundle and product == group.products.first %}&lt;br /&gt;
      &amp;lt;div class=&amp;quot;bundle-plus&amp;quot;&amp;gt;+&amp;lt;/div&amp;gt;&lt;br /&gt;
      {% endif %}&lt;br /&gt;
      {% if group.bundle and product == group.products.last %}&lt;br /&gt;
      &amp;lt;div class=&amp;quot;bundle-plus&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;a href=&amp;quot;{{ bundle.buy_link }}&amp;quot;&amp;gt;{{ bundle.text }}&amp;lt;/a&amp;gt;&lt;br /&gt;
      &amp;lt;/div&amp;gt;&lt;br /&gt;
      {% endif %}&lt;br /&gt;
      {% endfor %}&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
  {% endfor %}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Lucijan</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Shopify_Liquid</id>
		<title>Shopify Liquid</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Shopify_Liquid"/>
				<updated>2013-10-07T16:27:18Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also our page with [[Shopify Liquid Examples]].&lt;br /&gt;
&lt;br /&gt;
== Liquid variables supported by Directed Edge ==&lt;br /&gt;
=== &amp;lt;tt&amp;gt;groups&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
The liquid variable groups contain all recommendation types that are available for the requested page. Each group has following properties:&lt;br /&gt;
{| class=&amp;quot;variable-ref-table&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| label || A formatted label of the group, for example, “Recommended Items”, “Recently Viewed”, etc. Those labels can be customized in our [http://shopify.directededge.com/settings#styling Appearance Settings].&lt;br /&gt;
|-&lt;br /&gt;
| handle || A machine friendly identifier for the group (e.g. &amp;lt;tt&amp;gt;bundle&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;recommended_product&amp;lt;/tt&amp;gt;, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| products || An array of all of the products in returned for this recommendations group.&lt;br /&gt;
The following example would print title and price of all products in all available groups:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
{% for group in groups %}&lt;br /&gt;
  &amp;lt;ul&amp;gt;&lt;br /&gt;
  {% for product in group.products %}&lt;br /&gt;
    &amp;lt;li&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;{{ product.title }}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
    {{ product.price | money }}&lt;br /&gt;
  {% endfor %}&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
{% endfor %}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A detailed description of all product’s properties can be found [http://docs.shopify.com/themes/liquid-variables/product here].&lt;br /&gt;
|-&lt;br /&gt;
| bundle || A boolean field that indicates if this group is a bundle. This is useful to render custom content for that particular group. The following snippet would display both product images separated by a plus sign and followed by a equals sign and the bundle price:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
{% for group in groups %}&lt;br /&gt;
  {% if group.bundle %}&lt;br /&gt;
    {{ group.products.first.featured_image | product_img_url: &amp;#039;small&amp;#039; }}&lt;br /&gt;
    +&lt;br /&gt;
    {{ group.products.last.featured_image | product_img_url: &amp;#039;small&amp;#039; }}&lt;br /&gt;
    =&lt;br /&gt;
    {{ bundle.price }}&lt;br /&gt;
  {% else %}&lt;br /&gt;
    &amp;lt;!-- render other content here --&amp;gt;&lt;br /&gt;
  {% endif %}&lt;br /&gt;
{% endfor %}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;bundle&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
The bundle variable is used to access extra information about bundles, not available in other groups:&lt;br /&gt;
{| class=&amp;quot;variable-ref-table&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| text || Bundle’s buy message (e.g. “Buy both for $20”) which can be adjusted in the [http://shopify.directededge.com/settings#bundle Directed Edge for Shopify Bundle Settings] page.&lt;br /&gt;
|-&lt;br /&gt;
| price || The total price of a bundle calculated using the method specified in the [http://shopify.directededge.com/settings#bundle Directed Edge for Shopify Bundle Settings] page.  It can be formatted with the price filter just like elsewhere in Shopify templates: &amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;{{ bundle.price | money }}&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| buy_link || A link that will add both products to the shopping cart and will ask the user to pick a variant if multiple variants are available for the bundled products.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;product&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
We support the same variables as Shopify, with the following additions.  See their documentation for &amp;lt;tt&amp;gt;[http://docs.shopify.com/themes/liquid-variables/product product]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;variable-ref-table&amp;quot;&lt;br /&gt;
| buy_link || A link that will add the product to the shopping cart and will ask the user to pick a variant if multiple variants are available for the product.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Lucijan</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Shopify_Javascript_Callbacks</id>
		<title>Shopify Javascript Callbacks</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Shopify_Javascript_Callbacks"/>
				<updated>2012-10-23T06:32:46Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
== Add a hover effect to the recommendations (jQuery) ==&lt;br /&gt;
&lt;br /&gt;
This changes the text color and the border color of the image simultaneously.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{% assign directed-edge-callback = &amp;#039;addHoverEffectToRecommendations&amp;#039; %}&lt;br /&gt;
{% include &amp;#039;directed-edge&amp;#039; %}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
function addHoverEffectToRecommendations() {&lt;br /&gt;
    function findIndexInRow(e) {&lt;br /&gt;
        var children = e.parentElement.children;&lt;br /&gt;
        for(var i = 0; i &amp;lt; children.length; i++) { if(children[i] == e) { return i; } }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function findTitleForImage(e) {&lt;br /&gt;
        return $(e.parentElement).next().children()[findIndexInRow(e)];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function findImageForTitle(e) {&lt;br /&gt;
        return $(e.parentElement).prev().children()[findIndexInRow(e)];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $(&amp;quot;.directededge-image-cell&amp;quot;).hover(function() {&lt;br /&gt;
        $(&amp;quot;img&amp;quot;, this).css(&amp;quot;border-color&amp;quot;, &amp;quot;#DDD&amp;quot;);&lt;br /&gt;
        $(&amp;quot;a&amp;quot;, findTitleForImage(this)).css(&amp;quot;color&amp;quot;, &amp;quot;#FD885D&amp;quot;);&lt;br /&gt;
    }, function() {&lt;br /&gt;
        $(&amp;quot;img&amp;quot;, this).css(&amp;quot;border-color&amp;quot;, &amp;quot;#FFF&amp;quot;);&lt;br /&gt;
        $(&amp;quot;a&amp;quot;, findTitleForImage(this)).css(&amp;quot;color&amp;quot;, &amp;quot;#242424&amp;quot;);&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $(&amp;quot;.directededge-title-cell&amp;quot;).hover(function() {&lt;br /&gt;
        $(&amp;quot;img&amp;quot;, findImageForTitle(this)).css(&amp;quot;border-color&amp;quot;, &amp;quot;#DDD&amp;quot;);&lt;br /&gt;
        $(&amp;quot;a&amp;quot;, this).css(&amp;quot;color&amp;quot;, &amp;quot;#FD885D&amp;quot;);&lt;br /&gt;
    }, function() {&lt;br /&gt;
        $(&amp;quot;img&amp;quot;, findImageForTitle(this)).css(&amp;quot;border-color&amp;quot;, &amp;quot;#FFF&amp;quot;);&lt;br /&gt;
        $(&amp;quot;a&amp;quot;, this).css(&amp;quot;color&amp;quot;, &amp;quot;#242424&amp;quot;);&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Add the items to the DOM tree without any styling ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{% assign directed-edge-jsonp = &amp;#039;showRecommendations&amp;#039; %}&lt;br /&gt;
{% include &amp;#039;directed-edge&amp;#039; %}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
function showRecommendations(data)&lt;br /&gt;
{&lt;br /&gt;
    var container = document.getElementById(&amp;quot;directededge-blocks&amp;quot;);&lt;br /&gt;
    var products = data.related_products;&lt;br /&gt;
&lt;br /&gt;
    for(var i = 0; i &amp;lt; products.length; i++)&lt;br /&gt;
    {&lt;br /&gt;
        var item = document.createElement(&amp;quot;div&amp;quot;);&lt;br /&gt;
        container.appendChild(item);&lt;br /&gt;
        item.className = &amp;quot;directededge-item&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        var imageLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
        item.appendChild(imageLink);&lt;br /&gt;
        imageLink.className = &amp;quot;directededge-image-link&amp;quot;;&lt;br /&gt;
        imageLink.href = products[i].link;&lt;br /&gt;
&lt;br /&gt;
        var image = document.createElement(&amp;quot;img&amp;quot;);&lt;br /&gt;
        imageLink.appendChild(image);&lt;br /&gt;
        image.className = &amp;quot;directededge-image&amp;quot;;&lt;br /&gt;
        image.src = products[i].image;&lt;br /&gt;
&lt;br /&gt;
        var title = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
        item.appendChild(title);&lt;br /&gt;
        title.className = &amp;quot;directededge-title&amp;quot;;&lt;br /&gt;
        title.href = products[i].link;&lt;br /&gt;
        title.innerHTML = products[i].title;&lt;br /&gt;
&lt;br /&gt;
        var price = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
        item.appendChild(price);&lt;br /&gt;
        price.className = &amp;quot;directededge-price&amp;quot;;&lt;br /&gt;
        price.href = products[i].link;&lt;br /&gt;
        price.innerHTML = products[i].price;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Truncate recommendation titles (jQuery) ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
{% assign directed-edge-callback = &amp;#039;truncateRecommendationTitles&amp;#039; %}&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
function truncateRecommendationTitles() {&lt;br /&gt;
 var max = 10;&lt;br /&gt;
 $(&amp;quot;.directededge-title-cell a&amp;quot;).each(function() {&lt;br /&gt;
   if(this.innerHTML.length &amp;gt; max) {&lt;br /&gt;
     this.innerHTML = this.innerHTML.substr(0, max - 3) + &amp;quot;...&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Getting_started_with_Spree/Products/Index</id>
		<title>Getting started with Spree/Products/Index</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Getting_started_with_Spree/Products/Index"/>
				<updated>2010-11-28T09:18:23Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: Created page with &amp;quot;&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt; &amp;lt;% unless edgy_recommended.empty? %&amp;gt;   &amp;lt;h3 class=&amp;quot;list-type&amp;quot;&amp;gt;&amp;lt;%= edgy_message %&amp;gt;&amp;lt;/h3&amp;gt;   &amp;lt;ul class=&amp;quot;product-listing&amp;quot;&amp;gt;     &amp;lt;% edgy_recommended.each do |...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;% unless edgy_recommended.empty? %&amp;gt;&lt;br /&gt;
  &amp;lt;h3 class=&amp;quot;list-type&amp;quot;&amp;gt;&amp;lt;%= edgy_message %&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
  &amp;lt;ul class=&amp;quot;product-listing&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;% edgy_recommended.each do |product| %&amp;gt;&lt;br /&gt;
      &amp;lt;li id=&amp;quot;product_&amp;lt;%= product.id %&amp;gt;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;%= link_to small_image(product), product %&amp;gt;&lt;br /&gt;
        &amp;lt;%= link_to raw(product.name + &amp;quot; &amp;lt;span class=&amp;#039;price selling&amp;#039;&amp;gt;#{product_price(product)}&amp;lt;/span&amp;gt;&amp;quot;), product, :class =&amp;gt; &amp;#039;info&amp;#039; %&amp;gt;&lt;br /&gt;
      &amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
  &amp;lt;h3 class=&amp;quot;list-type&amp;quot;&amp;gt;Our catalog:&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;% end %&amp;gt;&lt;br /&gt;
&amp;lt;% content_for :sidebar do %&amp;gt;&lt;br /&gt;
  &amp;lt;% hook :homepage_sidebar_navigation do %&amp;gt;&lt;br /&gt;
    &amp;lt;% if &amp;quot;products&amp;quot; == @current_controller &amp;amp;&amp;amp; @taxon %&amp;gt;&lt;br /&gt;
      &amp;lt;%= render &amp;quot;shared/filters&amp;quot; %&amp;gt;&lt;br /&gt;
    &amp;lt;% else %&amp;gt;&lt;br /&gt;
      &amp;lt;%= render &amp;quot;shared/taxonomies&amp;quot; %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
  &amp;lt;% end %&amp;gt;&lt;br /&gt;
&amp;lt;% end %&amp;gt;&lt;br /&gt;
&amp;lt;% if params[:keywords] %&amp;gt;&lt;br /&gt;
  &amp;lt;% hook :search_results do %&amp;gt;&lt;br /&gt;
    &amp;lt;% if @products.empty? %&amp;gt;&lt;br /&gt;
      &amp;lt;%= t(:no_products_found) %&amp;gt;&lt;br /&gt;
    &amp;lt;% else %&amp;gt;&lt;br /&gt;
      &amp;lt;%= render &amp;quot;shared/products&amp;quot;, :products =&amp;gt; @products, :taxon =&amp;gt; @taxon %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
  &amp;lt;% end %&amp;gt;&lt;br /&gt;
&amp;lt;% else %&amp;gt;&lt;br /&gt;
  &amp;lt;% hook :homepage_products do %&amp;gt;&lt;br /&gt;
    &amp;lt;%= render &amp;quot;shared/products&amp;quot;, :products =&amp;gt; @products, :taxon =&amp;gt; @taxon %&amp;gt;&lt;br /&gt;
  &amp;lt;% end %&amp;gt;&lt;br /&gt;
&amp;lt;% end %&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Getting_started_with_Spree/Orders/Form</id>
		<title>Getting started with Spree/Orders/Form</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Getting_started_with_Spree/Orders/Form"/>
				<updated>2010-11-28T09:13:02Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: Created page with &amp;quot;&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt; &amp;lt;%= error_messages_for :order  %&amp;gt; &amp;lt;table id=&amp;quot;cart-detail&amp;quot;&amp;gt;   &amp;lt;thead&amp;gt;     &amp;lt;tr&amp;gt;       &amp;lt;% hook :cart_items_headers do %&amp;gt;         &amp;lt;th colspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;%= t(&amp;quot;i...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;%= error_messages_for :order  %&amp;gt;&lt;br /&gt;
&amp;lt;table id=&amp;quot;cart-detail&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;thead&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;% hook :cart_items_headers do %&amp;gt;&lt;br /&gt;
        &amp;lt;th colspan=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;%= t(&amp;quot;item&amp;quot;) %&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;
        &amp;lt;th&amp;gt;&amp;lt;%= t(&amp;quot;price&amp;quot;) %&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;
        &amp;lt;th&amp;gt;&amp;lt;%= t(&amp;quot;qty&amp;quot;) %&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;
        &amp;lt;th&amp;gt;&amp;lt;%= t(&amp;quot;total&amp;quot;) %&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;
        &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;% end %&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/thead&amp;gt;&lt;br /&gt;
  &amp;lt;tbody id=&amp;quot;line_items&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;% order_form.fields_for :line_items do |item_form| %&amp;gt;&lt;br /&gt;
      &amp;lt;%= render &amp;#039;line_item&amp;#039;, :variant =&amp;gt; item_form.object.variant, :line_item =&amp;gt; item_form.object, :item_form =&amp;gt; item_form %&amp;gt;&lt;br /&gt;
    &amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;% if @order.line_items.empty? -%&amp;gt;&lt;br /&gt;
      &amp;lt;tr id=&amp;quot;none&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;td colspan=&amp;quot;5&amp;quot;&amp;gt;&amp;lt;%= t(&amp;quot;your_cart_is_empty.&amp;quot;) -%&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;% end -%&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;%= edgy_related_table :horizontal, :max_results =&amp;gt; 5 %&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Getting_started_with_Spree/Products/Show</id>
		<title>Getting started with Spree/Products/Show</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Getting_started_with_Spree/Products/Show"/>
				<updated>2010-11-28T08:43:00Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: Created page with &amp;quot;&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt; &amp;lt;% @body_id = &amp;#039;product-details&amp;#039; %&amp;gt; &amp;lt;h1&amp;gt;&amp;lt;%= @product.name %&amp;gt;&amp;lt;/h1&amp;gt;  &amp;lt;div id=&amp;quot;product-images&amp;quot;&amp;gt;   &amp;lt;div id=&amp;quot;main-image&amp;quot;&amp;gt;     &amp;lt;%= render &amp;#039;image&amp;#039; -%&amp;gt;   &amp;lt;/div...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;html4strict&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;% @body_id = &amp;#039;product-details&amp;#039; %&amp;gt;&lt;br /&gt;
&amp;lt;h1&amp;gt;&amp;lt;%= @product.name %&amp;gt;&amp;lt;/h1&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;product-images&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;main-image&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;%= render &amp;#039;image&amp;#039; -%&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;thumbnails&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;%= render &amp;#039;thumbnails&amp;#039;, :product =&amp;gt; @product -%&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;% hook :cart_form do %&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;cart-form&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;%= render &amp;#039;cart_form&amp;#039; %&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;% end %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;product-description&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;% hook :product_description do %&amp;gt;&lt;br /&gt;
    &amp;lt;%= product_description(@product) rescue t(&amp;quot;product_has_no_description&amp;quot;) %&amp;gt;&lt;br /&gt;
  &amp;lt;% end %&amp;gt;&lt;br /&gt;
  &amp;lt;% hook :product_properties do %&amp;gt;&lt;br /&gt;
    &amp;lt;%= render &amp;#039;properties&amp;#039; %&amp;gt;&lt;br /&gt;
  &amp;lt;% end %&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;%= edgy_related_table :vertical, :max_results =&amp;gt; 4 %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;%= render &amp;#039;taxons&amp;#039; %&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Getting_started_for_Java_developers</id>
		<title>Getting started for Java developers</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Getting_started_for_Java_developers"/>
				<updated>2009-11-23T18:14:26Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GettingStarted|Java|Java/dist/com.directededge.jar|You&amp;#039;ll also need the included com.noelios.restlet.jar and org.restlet.jar from Java/dist/lib.}}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
Currently there&amp;#039;s no ExampleStore example like there are for [[ExampleStore PHP|PHP]], [[ExampleStore Python|Python]] and [[ExampleStore Ruby|Ruby]], but since the bindings follow very closely to the bindings in those languages, it&amp;#039;s probably still worth your time to glance at one of those.&lt;br /&gt;
&lt;br /&gt;
You&amp;#039;ll also find several files in &amp;lt;tt&amp;gt;Java/test&amp;lt;/tt&amp;gt; in the bindings that should give you a bit of an idea of how the Java API fits together.&lt;br /&gt;
{{FurtherReading}}&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Getting_started_for_Ruby_developers</id>
		<title>Getting started for Ruby developers</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Getting_started_for_Ruby_developers"/>
				<updated>2009-11-23T18:07:52Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: Add gem.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GettingStarted|Ruby|Ruby/directed_edge.rb|You&amp;#039;ll need to make sure you have rubygems and the rest_client Gem installed.  Alternatively, you can install our [http://gemcutter.org/gems/directed-edge Gem] directly with &amp;lt;tt&amp;gt;sudo gem install directed-edge&amp;lt;/tt&amp;gt;.}}&lt;br /&gt;
== Tutorial ==&lt;br /&gt;
&lt;br /&gt;
* [[Ruby Bindings for E-Commerce Tutorial]] provides a detailed step-by-step walkthrough of how to get up and going with a store &amp;amp;mdash; it&amp;#039;s based on the same code as below, but with lots of details.&lt;br /&gt;
&lt;br /&gt;
{{ExampleStore|ExampleStore Ruby}}&lt;br /&gt;
{{FurtherReading}}&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/ExampleStore_PHP</id>
		<title>ExampleStore PHP</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/ExampleStore_PHP"/>
				<updated>2009-11-23T17:53:30Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Ok, so the basics of how this thing works:&lt;br /&gt;
 *&lt;br /&gt;
 * It assumes that you have a local database for your store, and that store&lt;br /&gt;
 * has a &amp;quot;customer&amp;quot; table and &amp;quot;products&amp;quot; table.  In each of those tables&lt;br /&gt;
 * you have a unique ID that corresponds to each customer and product,&lt;br /&gt;
 * respectively.&lt;br /&gt;
 *&lt;br /&gt;
 * It also assumes there&amp;#039;s a third table, named &amp;quot;purchases&amp;quot; that has a list of&lt;br /&gt;
 * things purchased by customers.  Basically a mapping from the customer ID to&lt;br /&gt;
 * the product ID.  All of this is pretty standard store stuff.&lt;br /&gt;
 *&lt;br /&gt;
 * So, then what this class does is it handles:&lt;br /&gt;
 *&lt;br /&gt;
 * - Getting that data from those tables over to Directed Edge&lt;br /&gt;
 * - Doing incremental updates (adding customers, products, purchases)&lt;br /&gt;
 * - Finding products related to a given product&lt;br /&gt;
 * - Finding personalized product recommendations for a customer&lt;br /&gt;
 *&lt;br /&gt;
 * This is really just the starting point; there are some other exciting things&lt;br /&gt;
 * that can be done with the API once you&amp;#039;ve gotten your feet wet.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
define(&amp;#039;DB_HOST&amp;#039;, &amp;#039;localhost&amp;#039;);&lt;br /&gt;
define(&amp;#039;DB_USER&amp;#039;, &amp;#039;examplestore&amp;#039;);&lt;br /&gt;
define(&amp;#039;DB_PASS&amp;#039;, &amp;#039;password&amp;#039;);&lt;br /&gt;
define(&amp;#039;DB_NAME&amp;#039;, &amp;#039;examplestore&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
define(&amp;#039;DIRECTEDEDGE_USER&amp;#039;, &amp;#039;examplestore&amp;#039;);&lt;br /&gt;
define(&amp;#039;DIRECTEDEDGE_PASS&amp;#039;, &amp;#039;password&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
define(&amp;#039;EXPORT_FILE&amp;#039;, &amp;#039;examplestore.xml&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
class ExampleStore&lt;br /&gt;
{&lt;br /&gt;
    private $database;&lt;br /&gt;
&lt;br /&gt;
    public function __construct()&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
        mysql_connect(DB_HOST, DB_USER, DB_PASS);&lt;br /&gt;
&lt;br /&gt;
        if(!mysql_select_db(DB_NAME))&lt;br /&gt;
        {&lt;br /&gt;
            throw new Exception(&amp;quot;Could not connect to DB.&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;database = new DirectedEdgeDatabase(DIRECTEDEDGE_USER, DIRECTEDEDGE_PASS);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Export the list of products, purchases and customers to an XML file that&lt;br /&gt;
     * we can later push to the Directed Edge webservices.&lt;br /&gt;
     */&lt;br /&gt;
&lt;br /&gt;
    public function exportFromMySQL()&lt;br /&gt;
    {&lt;br /&gt;
        $exporter = new DirectedEdgeExporter(EXPORT_FILE);&lt;br /&gt;
&lt;br /&gt;
        foreach($this-&amp;gt;getProducts() as $product)&lt;br /&gt;
        {&lt;br /&gt;
            $item = new DirectedEdgeItem($exporter-&amp;gt;getDatabase(), &amp;#039;product&amp;#039; . $product);&lt;br /&gt;
            $item-&amp;gt;addTag(&amp;#039;product&amp;#039;);&lt;br /&gt;
            $exporter-&amp;gt;export($item);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        foreach($this-&amp;gt;getCustomers() as $customer)&lt;br /&gt;
        {&lt;br /&gt;
            $item = new DirectedEdgeItem($exporter-&amp;gt;getDatabase(), &amp;#039;customer&amp;#039; . $customer);&lt;br /&gt;
&lt;br /&gt;
            foreach($this-&amp;gt;getPurchasesForCustomer($customer) as $product)&lt;br /&gt;
            {&lt;br /&gt;
                $item-&amp;gt;linkTo(&amp;#039;product&amp;#039; . $product);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            $exporter-&amp;gt;export($item);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $exporter-&amp;gt;finish();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Import the file that we created using exportFromMySQL to the Directed Edge&lt;br /&gt;
     * webservices.&lt;br /&gt;
     */&lt;br /&gt;
&lt;br /&gt;
    public function importToDirectedEdge()&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;database-&amp;gt;import(EXPORT_FILE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Create a customer in the Directed Edge database that corresponds to the&lt;br /&gt;
     * customer in the local database with $id.&lt;br /&gt;
     */&lt;br /&gt;
&lt;br /&gt;
    public function createCustomer($id)&lt;br /&gt;
    {&lt;br /&gt;
        $item = new DirectedEdgeItem($this-&amp;gt;database, &amp;#039;customer&amp;#039; . $id);&lt;br /&gt;
        $item-&amp;gt;addTag(&amp;#039;customer&amp;#039;);&lt;br /&gt;
        $item-&amp;gt;save();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Create a product in the Directed Edge database that corresponds to the&lt;br /&gt;
     * product in the local database with $id.&lt;br /&gt;
     */&lt;br /&gt;
&lt;br /&gt;
    public function createProduct($id)&lt;br /&gt;
    {&lt;br /&gt;
        $item = new DirectedEdgeItem($this-&amp;gt;database, &amp;#039;product&amp;#039; . $id);&lt;br /&gt;
        $item-&amp;gt;addTag(&amp;#039;product&amp;#039;);&lt;br /&gt;
        $item-&amp;gt;save();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Create a purchase in the Directed Edge database from the product with&lt;br /&gt;
     * the local database IDs $customerId and $productId.&lt;br /&gt;
     */&lt;br /&gt;
&lt;br /&gt;
    public function addPurchase($customerId, $productId)&lt;br /&gt;
    {&lt;br /&gt;
        $item = new DirectedEdgeItem($this-&amp;gt;database, &amp;#039;customer&amp;#039; . $customerId);&lt;br /&gt;
        $item-&amp;gt;linkTo(&amp;#039;product&amp;#039; . $productId);&lt;br /&gt;
        $item-&amp;gt;save();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Returns a list of related product IDs for the product ID that&amp;#039;s passed in.&lt;br /&gt;
     */&lt;br /&gt;
&lt;br /&gt;
    public function getRelatedProducts($productId)&lt;br /&gt;
    {&lt;br /&gt;
        $item = new DirectedEdgeItem($this-&amp;gt;database, &amp;#039;product&amp;#039; . $productId);&lt;br /&gt;
        $related = array();&lt;br /&gt;
&lt;br /&gt;
        foreach($item-&amp;gt;getRelated(array(&amp;#039;product&amp;#039;)) as $item)&lt;br /&gt;
        {&lt;br /&gt;
            $related[] = str_replace(&amp;#039;product&amp;#039;, &amp;#039;&amp;#039;, $item);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return $related;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Returns a list of recommended products for the customer ID that&amp;#039;s passed in.&lt;br /&gt;
     */&lt;br /&gt;
&lt;br /&gt;
    public function getPersonalizedRecommendations($customerId)&lt;br /&gt;
    {&lt;br /&gt;
        $item = new DirectedEdgeItem($this-&amp;gt;database, &amp;#039;customer&amp;#039; . $customerId);&lt;br /&gt;
        $recommended = array();&lt;br /&gt;
&lt;br /&gt;
        foreach($item-&amp;gt;getRecommended(array(&amp;#039;product&amp;#039;)) as $item)&lt;br /&gt;
        {&lt;br /&gt;
            $recommended[] = str_replace(&amp;#039;product&amp;#039;, &amp;#039;&amp;#039;, $item);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return $recommended;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private function getCustomers()&lt;br /&gt;
    {&lt;br /&gt;
        $result = mysql_query(&amp;quot;select id from customers&amp;quot;);&lt;br /&gt;
        $customers = array();&lt;br /&gt;
&lt;br /&gt;
        while($row = mysql_fetch_row($result))&lt;br /&gt;
        {&lt;br /&gt;
            $customers[] = $row[0];&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return $customers;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private function getProducts()&lt;br /&gt;
    {&lt;br /&gt;
        $result = mysql_query(&amp;quot;select id from products&amp;quot;);&lt;br /&gt;
        $products = array();&lt;br /&gt;
&lt;br /&gt;
        while($row = mysql_fetch_row($result))&lt;br /&gt;
        {&lt;br /&gt;
            $products[] = $row[0];&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return $products;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private function getPurchasesForCustomer($customer)&lt;br /&gt;
    {&lt;br /&gt;
        $result = mysql_query(sprintf(&amp;quot;select product from purchases where customer = &amp;#039;%s&amp;#039;&amp;quot;,&lt;br /&gt;
                                      mysql_real_escape_string($customer)));&lt;br /&gt;
        $purchases = array();&lt;br /&gt;
&lt;br /&gt;
        while($row = mysql_fetch_row($result))&lt;br /&gt;
        {&lt;br /&gt;
            $purchases[] = $row[0];&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return $purchases;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$store = new ExampleStore();&lt;br /&gt;
$store-&amp;gt;exportFromMySQL();&lt;br /&gt;
$store-&amp;gt;importToDirectedEdge();&lt;br /&gt;
&lt;br /&gt;
$store-&amp;gt;createCustomer(1000);&lt;br /&gt;
$store-&amp;gt;createProduct(1000);&lt;br /&gt;
$store-&amp;gt;addPurchase(1000, 1000);&lt;br /&gt;
&lt;br /&gt;
print_r($store-&amp;gt;getRelatedProducts(2));&lt;br /&gt;
print_r($store-&amp;gt;getPersonalizedRecommendations(2));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Getting_started_for_Python_developers</id>
		<title>Getting started for Python developers</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Getting_started_for_Python_developers"/>
				<updated>2009-11-23T17:46:37Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GettingStarted|Python|Python/directed_edge.py|You&amp;#039;ll need to make sure you have urllib, urllib2 and httplib2 installed.  We used [http://peak.telecommunity.com/DevCenter/EasyInstall easy_install] to grab them.}}&lt;br /&gt;
{{ExampleStore|ExampleStore Python}}&lt;br /&gt;
{{FurtherReading}}&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Getting_started_for_PHP_developers</id>
		<title>Getting started for PHP developers</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Getting_started_for_PHP_developers"/>
				<updated>2009-11-23T17:31:43Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GettingStarted|PHP|PHP/DirectedEdge.php|You&amp;#039;ll also want to make sure that you have [http://pear.php.net/ Pear] and [http://pear.php.net/package/HTTP_Request2/ HTTP_Request2] installed to use the bindings.}}&lt;br /&gt;
{{ExampleStore|ExampleStore PHP}}&lt;br /&gt;
{{FurtherReading}}&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Python_ExampleStore</id>
		<title>Python ExampleStore</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Python_ExampleStore"/>
				<updated>2009-08-10T10:46:16Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039; You will need to change the usernames / passwords in the &amp;lt;tt&amp;gt;ExampleStore&amp;lt;/tt&amp;gt; constructor.&lt;br /&gt;
&lt;br /&gt;
:&amp;#039;&amp;#039;Comments will follow, but the flow is identical to the [[Ruby Bindings for E-Commerce Tutorial]]&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
from sqlalchemy import Column, Integer, create_engine&lt;br /&gt;
from sqlalchemy.ext.declarative import declarative_base&lt;br /&gt;
from sqlalchemy.orm import sessionmaker&lt;br /&gt;
&lt;br /&gt;
from directed_edge import Exporter, Item, Database&lt;br /&gt;
&lt;br /&gt;
Base = declarative_base()&lt;br /&gt;
&lt;br /&gt;
class Customer(Base):&lt;br /&gt;
    __tablename__ = &amp;quot;customers&amp;quot;&lt;br /&gt;
    id = Column(Integer, primary_key=True)&lt;br /&gt;
&lt;br /&gt;
class Product(Base):&lt;br /&gt;
    __tablename__ = &amp;quot;products&amp;quot;&lt;br /&gt;
    id = Column(Integer, primary_key=True)&lt;br /&gt;
&lt;br /&gt;
class Purchase(Base):&lt;br /&gt;
    __tablename__ = &amp;quot;purchases&amp;quot;&lt;br /&gt;
    customer = Column(Integer, primary_key=True)&lt;br /&gt;
    product = Column(Integer, primary_key=True)&lt;br /&gt;
&lt;br /&gt;
class ExampleStore(object):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        self.database = Database(&amp;quot;examplestore&amp;quot;, &amp;quot;password&amp;quot;)&lt;br /&gt;
        engine = create_engine(&amp;quot;mysql://examplestore:password@localhost/examplestore&amp;quot;)&lt;br /&gt;
        Session = sessionmaker(bind=engine)&lt;br /&gt;
        self.session = Session()&lt;br /&gt;
&lt;br /&gt;
    def export_from_mysql(self):&lt;br /&gt;
        exporter = Exporter(&amp;quot;examplestore.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        for product in self.session.query(Product):&lt;br /&gt;
            item = Item(exporter.database, &amp;quot;product%s&amp;quot; % product.id)&lt;br /&gt;
            item.add_tag(&amp;quot;product&amp;quot;)&lt;br /&gt;
            exporter.export(item)&lt;br /&gt;
            &lt;br /&gt;
        for customer in self.session.query(Customer):&lt;br /&gt;
            item = Item(exporter.database, &amp;quot;customer%s&amp;quot; % customer.id)&lt;br /&gt;
            item.add_tag(&amp;quot;customer&amp;quot;)&lt;br /&gt;
            for purchase in self.session.query(Purchase).filter_by(customer=customer.id):&lt;br /&gt;
                item.link_to(&amp;quot;product%s&amp;quot; % purchase.product)&lt;br /&gt;
            exporter.export(item)&lt;br /&gt;
&lt;br /&gt;
        exporter.finish()&lt;br /&gt;
&lt;br /&gt;
    def import_to_directededge(self):&lt;br /&gt;
        self.database.import_from_file(&amp;quot;examplestore.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def create_customer(self, id):&lt;br /&gt;
        item = Item(self.database, &amp;quot;customer%s&amp;quot; % id)&lt;br /&gt;
        item.add_tag(&amp;quot;customer&amp;quot;)&lt;br /&gt;
        item.save()&lt;br /&gt;
&lt;br /&gt;
    def create_product(self, id):&lt;br /&gt;
        item = Item(self.database, &amp;quot;product%s&amp;quot; % id)&lt;br /&gt;
        item.add_tag(&amp;quot;product&amp;quot;)&lt;br /&gt;
        item.save()&lt;br /&gt;
&lt;br /&gt;
    def add_purchase(self, customer_id, product_id):&lt;br /&gt;
        item = Item(self.database, &amp;quot;customer%s&amp;quot; % customer_id)&lt;br /&gt;
        item.link_to(&amp;quot;product%s&amp;quot; % product_id)&lt;br /&gt;
        item.save()&lt;br /&gt;
&lt;br /&gt;
    def related_products(self, product_id):&lt;br /&gt;
        item = Item(self.database, &amp;quot;product%s&amp;quot; % product_id)&lt;br /&gt;
        return [related.replace(&amp;quot;product&amp;quot;, &amp;quot;&amp;quot;) for related in item.related([&amp;quot;product&amp;quot;])]&lt;br /&gt;
&lt;br /&gt;
    def personalized_recommendations(self, customer_id):&lt;br /&gt;
        item = Item(self.database, &amp;quot;customer%s&amp;quot; % customer_id)&lt;br /&gt;
        return [related.replace(&amp;quot;product&amp;quot;, &amp;quot;&amp;quot;) for related in item.recommended([&amp;quot;product&amp;quot;])]&lt;br /&gt;
        &lt;br /&gt;
store = ExampleStore()&lt;br /&gt;
store.export_from_mysql()&lt;br /&gt;
store.import_to_directededge()&lt;br /&gt;
&lt;br /&gt;
store.create_customer(1000)&lt;br /&gt;
store.create_product(1000)&lt;br /&gt;
store.add_purchase(1000, 1000)&lt;br /&gt;
&lt;br /&gt;
print store.related_products(2)&lt;br /&gt;
print store.personalized_recommendations(2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Ruby_Bindings_for_E-Commerce_Tutorial</id>
		<title>Ruby Bindings for E-Commerce Tutorial</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Ruby_Bindings_for_E-Commerce_Tutorial"/>
				<updated>2009-05-25T13:57:58Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;One of the main things that people often want to do is to integrate Directed Edge&amp;#039;s recommendation engine into their online store.  Many of those stores are using Ruby already, so we decided to give a very concrete walk-through of doing recommendations based on previous customer purchases starting from exporting data all the way to keeping it in sync.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;If you want to see all of the code in one go, you can get it in full syntax-highlighted glory here: [[ExampleStore Class]], or download it [[Media:example_store.rb|here]].  You&amp;#039;ll also want our Ruby bindings, which you can get from GitHub [http://github.com/directededge/directed-edge-bindings/blob/6f5f421d25f4b43e6b39cb35702987b5598cc85f/Ruby/directed_edge.rb here] ([http://github.com/directededge/directed-edge-bindings/raw/6f5f421d25f4b43e6b39cb35702987b5598cc85f/Ruby/directed_edge.rb download]).&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Not a Rubyist?  No problem.  You can use our API from any programming language, the language bindings just make things a little easier.  You still may get something out of reading through the example here to get a feel for the integration process.&lt;br /&gt;
&lt;br /&gt;
== Creating the testing database ==&lt;br /&gt;
&lt;br /&gt;
You&amp;#039;ve probably got your own site&amp;#039;s database that you&amp;#039;re more interested in, but if you want to follow along in the code, you can use the store data that we randomly generated.  We created 2000 users with 500 products and had each of those users &amp;quot;buy&amp;quot; between 0 and 30 products.&lt;br /&gt;
&lt;br /&gt;
For that we created three very simple tables.  Since we don&amp;#039;t care about the other properties of the customers or products, all that those tables contain is an ID.  The purchase table just contains &amp;#039;&amp;#039;customer&amp;#039;&amp;#039; and &amp;#039;&amp;#039;product&amp;#039;&amp;#039; columns.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table style=&amp;quot;padding: 0.5em; border: 1px solid #ccc; text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;customers&amp;lt;/tt&amp;gt; table:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background: #eee; padding: 0.2em;&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
! id&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;products&amp;lt;/tt&amp;gt; table:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background: #eee; padding: 0.2em;&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
! id&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;purchases&amp;lt;/tt&amp;gt; table:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background: #eee; padding: 0.2em;&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
! customer !! product&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It really can&amp;#039;t get much simpler than that.  &amp;#039;&amp;#039;&amp;#039;You can get a dump of the database [[Media:examplestore.mysql|here]].&amp;#039;&amp;#039;&amp;#039;  If you have a local MySQL running, you can create and import the database with these commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mysql --user=root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should now be at the MySQL prompt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mysql&amp;gt; create database examplestore;&lt;br /&gt;
mysql&amp;gt; create user &amp;#039;examplestore&amp;#039;@&amp;#039;localhost&amp;#039; identified by &amp;#039;password&amp;#039;;&lt;br /&gt;
mysql&amp;gt; grant all on examplestore.* to &amp;#039;examplestore&amp;#039;@&amp;#039;localhost&amp;#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now back at the command line do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mysql --user=examplestore -p examplestore &amp;lt; examplestore.mysql&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unless you changed the password above, the password is just &amp;#039;&amp;#039;password&amp;#039;&amp;#039;.  You&amp;#039;ve now got the same data that the examples use imported to a database called &amp;#039;&amp;#039;examplestore&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
== Setting up the Ruby plumbing ==&lt;br /&gt;
&lt;br /&gt;
Here we just do the standard ruby &amp;#039;&amp;#039;hashbang&amp;#039;&amp;#039; and import three modules.  Ruby gems is required since we&amp;#039;ve pulled in &amp;#039;&amp;#039;activerecord&amp;#039;&amp;#039; via [http://rubygems.org/ gem].  [http://ar.rubyonrails.org/ ActiveRecord] is the object relational mapping that is standard with [http://rubyonrails.org/ Ruby on Rails] and we&amp;#039;ll be using it to access our MySQL database.  And finally, we use the [http://github.com/directededge/directed-edge-bindings/tree/master Ruby bindings] for the Directed Edge API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/ruby&lt;br /&gt;
&lt;br /&gt;
require &amp;#039;rubygems&amp;#039;&lt;br /&gt;
require &amp;#039;activerecord&amp;#039;&lt;br /&gt;
require &amp;#039;directed_edge&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setting up ActiveRecord ==&lt;br /&gt;
&lt;br /&gt;
ActiveRecord handles connecting to the database for us and is the mechanism that most Ruby web apps use to do the same.  To connect with ActiveRecord we have to supply the usual information &amp;amp;mdash; database type, host, user name, password and database name.&lt;br /&gt;
&lt;br /&gt;
Based on the database that we imported above, these connection values should work.&lt;br /&gt;
&lt;br /&gt;
ActiveRecord also handles most of the magic of mapping Ruby classes to database tables.  It can figure out that the &amp;#039;&amp;#039;customers&amp;#039;&amp;#039; table corresponds to the &amp;#039;&amp;#039;Customer&amp;#039;&amp;#039; (and the some for &amp;#039;&amp;#039;products&amp;#039;&amp;#039; and &amp;#039;&amp;#039;purchases&amp;#039;&amp;#039;) just by inheriting from the ActiveRecord base class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
ActiveRecord::Base.establish_connection(:adapter =&amp;gt; &amp;#039;mysql&amp;#039;,&lt;br /&gt;
                                        :host =&amp;gt; &amp;#039;localhost&amp;#039;,&lt;br /&gt;
                                        :username =&amp;gt; &amp;#039;examplestore&amp;#039;,&lt;br /&gt;
                                        :password =&amp;gt; &amp;#039;password&amp;#039;,&lt;br /&gt;
                                        :database =&amp;gt; &amp;#039;examplestore&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
class Customer &amp;lt; ActiveRecord::Base&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class Product &amp;lt; ActiveRecord::Base&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class Purchase &amp;lt; ActiveRecord::Base&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In place of &amp;#039;&amp;#039;Customer&amp;#039;&amp;#039;, &amp;#039;&amp;#039;Product&amp;#039;&amp;#039; and &amp;#039;&amp;#039;Purchase&amp;#039;&amp;#039; you&amp;#039;ll want to substitute in the values that correspond to your database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ExampleStore class and constructor ==&lt;br /&gt;
&lt;br /&gt;
We call the class that we&amp;#039;re working with ExampleStore.  Again, you&amp;#039;ll want to change that to fit your needs.  Just as a reminder, the full source of the class is [[ExampleStore Class|here]].&lt;br /&gt;
&lt;br /&gt;
The interesting bit here is the connection to the Directed Edge database.  Since several methods in the class use the Directed Edge database, we just set up the connection once.  This, fairly obviously, assumes that your user / database name is &amp;#039;&amp;#039;examplestore&amp;#039;&amp;#039; and your password is &amp;#039;&amp;#039;password&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
class ExampleStore&lt;br /&gt;
  def initialize&lt;br /&gt;
    @database = DirectedEdge::Database.new(&amp;#039;examplestore&amp;#039;, &amp;#039;password&amp;#039;)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Exporting your data to a Directed Edge formatted XML file ==&lt;br /&gt;
&lt;br /&gt;
Communication with the Directed Edge database is all done with our [[XML Format]].  The Ruby bindings make it easy to create files in that format that you can later import to your Directed Edge database.&lt;br /&gt;
&lt;br /&gt;
=== Basic algorithm ===&lt;br /&gt;
&lt;br /&gt;
* Create an instance of DirectedEdge::Exporter to export the items you&amp;#039;re creating&lt;br /&gt;
* Loop through all of the customers in your store, creating a DirectedEdge::Item for each customer, and marking it as a customer by giving it a &amp;#039;&amp;#039;customer&amp;#039;&amp;#039; tag&lt;br /&gt;
:* While looping through the customers, for each customer, also loop through all of their purchases, creating a link from the user to the purchased products&lt;br /&gt;
:* Export each of those items, with the freshly created links and tags in place&lt;br /&gt;
* Loop through all of the products in your store, creating a DirectedEdge::Item for each product, and marking it as a product by giving it a &amp;#039;&amp;#039;product&amp;#039;&amp;#039; tag&lt;br /&gt;
:* Export each of those items&lt;br /&gt;
* Tell the exporter that we&amp;#039;re done and it can finish up the XML&lt;br /&gt;
&lt;br /&gt;
=== ActiveRecord-fu ===&lt;br /&gt;
&lt;br /&gt;
For those not coming from a Rails background, things like the code to find all purchases matching a given customer ID might seem a bit off the wall:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;Purchase.find(:all, :conditions =&amp;gt; { :customer =&amp;gt; customer.id })&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That little thinger there does just what we described above &amp;amp;mdash; produces a list of all rows in the purchases table that have the customer ID specified.  ActiveRecord also automatically creates class accessors for each column of a table, so the &amp;#039;&amp;#039;.id&amp;#039;&amp;#039; there just corresponds to that column in the customers table.&lt;br /&gt;
&lt;br /&gt;
=== Encoding product and user IDs from the database ===&lt;br /&gt;
&lt;br /&gt;
In the MySQL tables the product table has a simple integer id field as does the customer table.  We want to encode those as unique identifiers for the Directed Edge database, which doesn&amp;#039;t have separate tables for different item types.&lt;br /&gt;
&lt;br /&gt;
So what we do is take the integer ID and prepend the words &amp;#039;&amp;#039;product&amp;#039;&amp;#039; and &amp;#039;&amp;#039;customer&amp;#039;&amp;#039;.  So the row from the MySQL customer table with the ID 1 becomes &amp;#039;&amp;#039;customer1&amp;#039;&amp;#039;.  The product from the MySQL product table with ID 2 becomes &amp;#039;&amp;#039;product2&amp;#039;&amp;#039;.  It&amp;#039;s not exactly rocket surgery.&lt;br /&gt;
&lt;br /&gt;
The code in the comments should help you with more fine-grained details.&lt;br /&gt;
&lt;br /&gt;
=== Output ===&lt;br /&gt;
&lt;br /&gt;
At the end you&amp;#039;ll have a file called &amp;#039;&amp;#039;examplestore.xml&amp;#039;&amp;#039; in the directory that you run the script.  You&amp;#039;ll naturally want to customize that to put it somewhere more appropriate (like, say, &amp;#039;&amp;#039;/tmp&amp;#039;&amp;#039;) when incorporating this with your own site.&lt;br /&gt;
&lt;br /&gt;
=== Implementation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
  def export_from_mysql&lt;br /&gt;
&lt;br /&gt;
    # Use the handy Directed Edge XML exporter to collect store data up to this&lt;br /&gt;
    # point&lt;br /&gt;
    exporter = DirectedEdge::Exporter.new(&amp;#039;examplestore.xml&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    # Loop through every customer in the database&lt;br /&gt;
    Customer.find(:all).each do |customer|&lt;br /&gt;
&lt;br /&gt;
      # Create a new item in the Directed Edge export file with the ID &amp;quot;customer12345&amp;quot;&lt;br /&gt;
      item = DirectedEdge::Item.new(exporter.database, &amp;quot;customer#{customer.id}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
      # Mark this item as a customer with a tag&lt;br /&gt;
      item.add_tag(&amp;#039;customer&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
      # Find all of the purchases for the current customer&lt;br /&gt;
      purchases = Purchase.find(:all, :conditions =&amp;gt; { :customer =&amp;gt; customer.id })&lt;br /&gt;
&lt;br /&gt;
      # For each purchase create a link from the customer to that item of the form&lt;br /&gt;
      # &amp;quot;product12345&amp;quot;&lt;br /&gt;
      purchases.each { |purchase| item.link_to(&amp;quot;product#{purchase.product}&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
      # And now write the item to the export file&lt;br /&gt;
      exporter.export(item)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Now go through all of the products creating items for them&lt;br /&gt;
    Product.find(:all).each do |product|&lt;br /&gt;
&lt;br /&gt;
      # Here we&amp;#039;ll also use the form &amp;quot;product12345&amp;quot; for our products&lt;br /&gt;
      item = DirectedEdge::Item.new(exporter.database, &amp;quot;product#{product.id}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
      # And mark it as a product with a tag&lt;br /&gt;
      item.add_tag(&amp;#039;product&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
      # And export it to the file&lt;br /&gt;
      exporter.export(item)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # We have to tell the exporter to clean up and finish up the file&lt;br /&gt;
    exporter.finish&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Customizing ===&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s here that the bulk of the customization work will be needed to map things to your store.  For starters you&amp;#039;ll need to do a search and replace for &amp;#039;&amp;#039;Customer&amp;#039;&amp;#039;, &amp;#039;&amp;#039;Product&amp;#039;&amp;#039; and &amp;#039;&amp;#039;Purchases&amp;#039;&amp;#039; for them to be the same ActiveRecord subclasses that you defined up at the top of the code and the names of those should correspond to your database tables.  You&amp;#039;ll also need to switch the attribute names from &amp;#039;&amp;#039;id&amp;#039;&amp;#039;, &amp;#039;&amp;#039;product&amp;#039;&amp;#039; and &amp;#039;&amp;#039;customer&amp;#039;&amp;#039; to whatever the corresponding columns are called in your database.  And as mentioned above, you&amp;#039;ll want to give the resulting XML file an appropriate home.&lt;br /&gt;
&lt;br /&gt;
You may also want to specify additional tags that correspond to product categories you might later want to filter on &amp;amp;mdash; &amp;#039;&amp;#039;book&amp;#039;&amp;#039; or &amp;#039;&amp;#039;album&amp;#039;&amp;#039;, for instance.  Since products can have as many tags as you like, you can create those in addition to the &amp;#039;&amp;#039;product&amp;#039;&amp;#039; and &amp;#039;&amp;#039;customer&amp;#039;&amp;#039; tags or use your own scheme entirely.&lt;br /&gt;
&lt;br /&gt;
== Importing the XML to the Directed Edge servers ==&lt;br /&gt;
&lt;br /&gt;
After all that muck above, this one&amp;#039;s nice and easy.  Once we&amp;#039;ve created the XML file using DirectedEdge::Exporter, it&amp;#039;s easy to import to our Directed Edge database.  Here we&amp;#039;re using the DirectedEdge::Database instance that we created in the constructor.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
  # Imports the file exported from the export method to the Directed Edge database&lt;br /&gt;
  def import_to_directededge&lt;br /&gt;
    @database.import(&amp;#039;examplestore.xml&amp;#039;)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only part you should have to modify here is making the file path correspond to where ever you decide to drop you XML export.&lt;br /&gt;
&lt;br /&gt;
== Adding new users / products ==&lt;br /&gt;
&lt;br /&gt;
With these two methods we repeat some of the logic used in the importer:&lt;br /&gt;
&lt;br /&gt;
* Create a new item with the identifier encoded as the type followed by an integer ID&lt;br /&gt;
* Add an appropriate tag to identify the item type&lt;br /&gt;
* Save the item (which uploads it to the Directed Edge server)&lt;br /&gt;
&lt;br /&gt;
You can choose to update your Directed Edge database incrementally using methods like these or import occasional snapshots using the import / export mechanism.  In most cases, doubly so for fast-changing data sets, it makes more sense to keep the Directed Edge database in sync with your local database this way.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
  # Creates a new customer in the Directed Edge database that corresponds to the&lt;br /&gt;
  # given customer ID&lt;br /&gt;
  def create_customer(id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;customer#{id}&amp;quot;)&lt;br /&gt;
    item.add_tag(&amp;#039;customer&amp;#039;)&lt;br /&gt;
    item.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Creates a new product in the Directed Edge database that corresponds to the&lt;br /&gt;
  # given product ID&lt;br /&gt;
  def create_product(id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;product#{id}&amp;quot;)&lt;br /&gt;
    item.add_tag(&amp;#039;product&amp;#039;)&lt;br /&gt;
    item.save&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you defined your own scheme for encoding items, you&amp;#039;ll need to update that appropriately; the same goes for tags.&lt;br /&gt;
&lt;br /&gt;
== Adding a new purchase ==&lt;br /&gt;
&lt;br /&gt;
As noted in the [[API Concepts]], a purchase for us is just a link between two items, here a customer and a product.  So, again, we encode the product and user names, create a new item corresponding to the customer and create a link between that item and the product&amp;#039;s identifier.&lt;br /&gt;
&lt;br /&gt;
Like we saw with adding new customers / products to the database, it&amp;#039;s usually best to issue these calls when your database is updated so that the data on our servers reflects the data in your database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
  # Notes in the Directed Edge database that customer_id purchased product_id&lt;br /&gt;
  def add_purchase(customer_id, product_id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;customer#{customer_id}&amp;quot;)&lt;br /&gt;
    item.link_to(&amp;quot;product#{product_id}&amp;quot;)&lt;br /&gt;
    item.save&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As usual, if you defined another means of mapping product integer IDs to Directed Edge item item identifiers, that will need to be reflected here.&lt;br /&gt;
&lt;br /&gt;
== Finding related products ==&lt;br /&gt;
&lt;br /&gt;
Now we get to the part where we deliver our first kind of recommendations &amp;amp;mdash; related products.  Some of the distinction between &amp;#039;&amp;#039;related&amp;#039;&amp;#039; and &amp;#039;&amp;#039;recommended&amp;#039;&amp;#039; items is discussed in the [[REST_API#Related_.2F_recommended_resources|REST API]] documentation.&lt;br /&gt;
&lt;br /&gt;
So, for products we want to find &amp;#039;&amp;#039;related&amp;#039;&amp;#039; products.  So we issue a &amp;#039;&amp;#039;related&amp;#039;&amp;#039; query on the product ID we&amp;#039;re interested in and specify that we&amp;#039;re only interested in things with the &amp;#039;&amp;#039;product&amp;#039;&amp;#039; tag.  The argument to &amp;#039;&amp;#039;related&amp;#039;&amp;#039; is a set of tags, so we give it an array (and Ruby sorts out turning that to a set).  In this case we only have one item in that array.&lt;br /&gt;
&lt;br /&gt;
We get back a list of identifiers and want to map those back to database IDs, so we substitute back out the &amp;#039;&amp;#039;product&amp;#039;&amp;#039; part of the strings and get just the integer part and map that back to an array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
  # Returns a list of product IDs related to the given product ID&lt;br /&gt;
  def related_products(product_id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;product#{product_id}&amp;quot;)&lt;br /&gt;
    item.related([&amp;#039;product&amp;#039;]).map { |product| product.sub(&amp;#039;product&amp;#039;, &amp;#039;&amp;#039;).to_i }&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once again, any changes you&amp;#039;ve made to the way that that items are encoded and tags you&amp;#039;re using will need to be reflected here.&lt;br /&gt;
&lt;br /&gt;
== Delivering personalized recommendations ==&lt;br /&gt;
&lt;br /&gt;
Much of the set up here is the same as related products above, except that now we&amp;#039;re working with a customer ID rather than a product ID.  The stripping out of the &amp;#039;&amp;#039;product&amp;#039;&amp;#039; part of the ID and mapping it back to a list of integers is the same.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
  # Returns a list of personalized recommendations for the given customer ID&lt;br /&gt;
  def personalized_recommendations(customer_id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;customer#{customer_id}&amp;quot;)&lt;br /&gt;
    item.recommended([&amp;#039;product&amp;#039;]).map { |product| product.sub(&amp;#039;product&amp;#039;, &amp;#039;&amp;#039;).to_i }&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Let&amp;#039;s give it a spin ==&lt;br /&gt;
&lt;br /&gt;
So, now we&amp;#039;ve finished defining our class, let&amp;#039;s do something with it!&lt;br /&gt;
&lt;br /&gt;
The example below shows:&lt;br /&gt;
&lt;br /&gt;
* Last line of the class definition (end)&lt;br /&gt;
* Exports the MySQL database to a file&lt;br /&gt;
* Sends that file up to the Directed Edge servers&lt;br /&gt;
* Creates a new customer (with ID 500), updating the MySQL database is left up to the reader&lt;br /&gt;
* Creates a new product (with ID 2000)&lt;br /&gt;
* Creates a new purchase (with the customer and product we just created)&lt;br /&gt;
* Retrieves and prints products related to the product with the (MySQL) ID of 1&lt;br /&gt;
* Retrieves and prints personalized recommendations for the user with the (MySQL) ID of 1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
store = ExampleStore.new&lt;br /&gt;
&lt;br /&gt;
# Export the contents of our MySQL database to XML&lt;br /&gt;
store.export_from_mysql&lt;br /&gt;
&lt;br /&gt;
# Import that XML to the Directed Edge database&lt;br /&gt;
store.import_to_directededge&lt;br /&gt;
&lt;br /&gt;
# Add a new customer&lt;br /&gt;
store.create_customer(500)&lt;br /&gt;
&lt;br /&gt;
# Add a new product&lt;br /&gt;
store.create_product(2000)&lt;br /&gt;
&lt;br /&gt;
# Set that user as having purchased that product&lt;br /&gt;
store.add_purchase(500, 2000)&lt;br /&gt;
&lt;br /&gt;
# Find related products for the product with the ID 1 (in MySQL)&lt;br /&gt;
store.related_products(1).each do |product|&lt;br /&gt;
  puts &amp;quot;Related products for product 1: #{product}&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
# Find personalized recommendations for the user with the ID 1 (in MySQL)&lt;br /&gt;
store.personalized_recommendations(1).each do |product|&lt;br /&gt;
  puts &amp;quot;Personalized recommendations for user 1: #{product}&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[ExampleStore Class]] - full source in one place of all of the examples covered here&lt;br /&gt;
* [[API Concepts]] - a refresher on the concepts at work here&lt;br /&gt;
* [[REST API]] and [[XML Format]] - A peek into what&amp;#039;s going on behind the scenes&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/ExampleStore_Class</id>
		<title>ExampleStore Class</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/ExampleStore_Class"/>
				<updated>2009-05-25T13:56:55Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/ruby&lt;br /&gt;
&lt;br /&gt;
require &amp;#039;rubygems&amp;#039;&lt;br /&gt;
require &amp;#039;activerecord&amp;#039;&lt;br /&gt;
require &amp;#039;directed_edge&amp;#039;&lt;br /&gt;
&lt;br /&gt;
ActiveRecord::Base.establish_connection(:adapter =&amp;gt; &amp;#039;mysql&amp;#039;,&lt;br /&gt;
                                        :host =&amp;gt; &amp;#039;localhost&amp;#039;,&lt;br /&gt;
                                        :username =&amp;gt; &amp;#039;examplestore&amp;#039;,&lt;br /&gt;
                                        :password =&amp;gt; &amp;#039;password&amp;#039;,&lt;br /&gt;
                                        :database =&amp;gt; &amp;#039;examplestore&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
class Customer &amp;lt; ActiveRecord::Base&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class Product &amp;lt; ActiveRecord::Base&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class Purchase &amp;lt; ActiveRecord::Base&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class ExampleStore&lt;br /&gt;
  def initialize&lt;br /&gt;
    @database = DirectedEdge::Database.new(&amp;#039;examplestore&amp;#039;, &amp;#039;password&amp;#039;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def export_from_mysql&lt;br /&gt;
    exporter = DirectedEdge::Exporter.new(&amp;#039;examplestore.xml&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    Customer.find(:all).each do |customer|&lt;br /&gt;
      item = DirectedEdge::Item.new(exporter.database, &amp;quot;customer#{customer.id}&amp;quot;)&lt;br /&gt;
      item.add_tag(&amp;#039;customer&amp;#039;)&lt;br /&gt;
      purchases = Purchase.find(:all, :conditions =&amp;gt; { :customer =&amp;gt; customer.id })&lt;br /&gt;
      purchases.each { |purchase| item.link_to(&amp;quot;product#{purchase.product}&amp;quot;) }&lt;br /&gt;
      exporter.export(item)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    Product.find(:all).each do |product|&lt;br /&gt;
      item = DirectedEdge::Item.new(exporter.database, &amp;quot;product#{product.id}&amp;quot;)&lt;br /&gt;
      item.add_tag(&amp;#039;product&amp;#039;)&lt;br /&gt;
      exporter.export(item)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    exporter.finish&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def import_to_directededge&lt;br /&gt;
    @database.import(&amp;#039;examplestore.xml&amp;#039;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def create_customer(id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;customer#{id}&amp;quot;)&lt;br /&gt;
    item.add_tag(&amp;#039;customer&amp;#039;)&lt;br /&gt;
    item.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def create_product(id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;product#{id}&amp;quot;)&lt;br /&gt;
    item.add_tag(&amp;#039;product&amp;#039;)&lt;br /&gt;
    item.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def add_purchase(customer_id, product_id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;customer#{customer_id}&amp;quot;)&lt;br /&gt;
    item.link_to(&amp;quot;product#{product_id}&amp;quot;)&lt;br /&gt;
    item.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def related_products(product_id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;product#{product_id}&amp;quot;)&lt;br /&gt;
    item.related([&amp;#039;product&amp;#039;]).map { |product| product.sub(&amp;#039;product&amp;#039;, &amp;#039;&amp;#039;).to_i }&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def personalized_recommendations(customer_id)&lt;br /&gt;
    item = DirectedEdge::Item.new(@database, &amp;quot;customer#{customer_id}&amp;quot;)&lt;br /&gt;
    item.recommended([&amp;#039;product&amp;#039;]).map { |product| product.sub(&amp;#039;product&amp;#039;, &amp;#039;&amp;#039;).to_i }&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
store = ExampleStore.new&lt;br /&gt;
&lt;br /&gt;
store.export_from_mysql&lt;br /&gt;
store.import_to_directededge&lt;br /&gt;
&lt;br /&gt;
store.create_customer(500)&lt;br /&gt;
store.create_product(2000)&lt;br /&gt;
store.add_purchase(500, 2000)&lt;br /&gt;
&lt;br /&gt;
store.related_products(1).each do |product|&lt;br /&gt;
  puts &amp;quot;Related products for product 1: #{product}&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
store.personalized_recommendations(1).each do |product|&lt;br /&gt;
  puts &amp;quot;Personalized recommendations for user 1: #{product}&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Web_Services_Examples</id>
		<title>Web Services Examples</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Web_Services_Examples"/>
				<updated>2009-05-24T05:27:05Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, now that you&amp;#039;ve been through the documentation on the [[API Concepts]], [[XML Format]] and [[REST API]], let&amp;#039;s take a look at a few practical examples of working with the Directed Edge webservices.&lt;br /&gt;
&lt;br /&gt;
For these examples we&amp;#039;ll be using the command line tool [http://curl.haxx.se/ curl] to upload XML to the webservices.&lt;br /&gt;
&lt;br /&gt;
== Importing a database ==&lt;br /&gt;
&lt;br /&gt;
Let&amp;#039;s start with a very simple database with three users (with the IDs &amp;#039;&amp;#039;user1&amp;#039;&amp;#039;, &amp;#039;&amp;#039;user2&amp;#039;&amp;#039; and &amp;#039;&amp;#039;user3&amp;#039;&amp;#039;) and three products (with the IDs &amp;#039;&amp;#039;product1&amp;#039;&amp;#039;, &amp;#039;&amp;#039;product2&amp;#039;&amp;#039; and &amp;#039;&amp;#039;product3&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product1&amp;lt;/link&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product2&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product3&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user3&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product2&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;product1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;product&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;product2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;product&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;product3&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;product&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CurlPut|database}}&lt;br /&gt;
&lt;br /&gt;
This imports the structure above into the &amp;#039;&amp;#039;exampledb&amp;#039;&amp;#039; database.&lt;br /&gt;
&lt;br /&gt;
== Exporting a database ==&lt;br /&gt;
&lt;br /&gt;
{{CurlGet}}&lt;br /&gt;
&lt;br /&gt;
Produces:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product1&amp;lt;/link&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product2&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product3&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user3&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product2&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;product1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;product&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;product2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;product&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;product3&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;product&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which is what we imported just above.&lt;br /&gt;
&lt;br /&gt;
== Adding an item ==&lt;br /&gt;
&lt;br /&gt;
Adds a user with the ID &amp;#039;&amp;#039;user4&amp;#039;&amp;#039; to the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user4&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CurlPut|user4|/items/user4}}&lt;br /&gt;
&lt;br /&gt;
== Updating an item ==&lt;br /&gt;
&lt;br /&gt;
Here we update the item above, but this time add the property &amp;#039;&amp;#039;city&amp;#039;&amp;#039;.  This overwrites all current contents of the item.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user4&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;city&amp;quot;&amp;gt;Berlin&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CurlPut|user4-update|/items/user4}}&lt;br /&gt;
&lt;br /&gt;
== Adding a tag to an item ==&lt;br /&gt;
&lt;br /&gt;
Here we add the tag &amp;#039;&amp;#039;Berliner&amp;#039;&amp;#039; to the user that we created / updated in the previous sections.  As noted in the [[XML Format]] description, here we&amp;#039;re allowed to omit the item&amp;#039;s ID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;Berliner&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CurlPut|tag|/items/user4/add}}&lt;br /&gt;
&lt;br /&gt;
== Adding a link to an item ==&lt;br /&gt;
&lt;br /&gt;
This creates a link from our recently created user to &amp;#039;&amp;#039;product3&amp;#039;&amp;#039;.  Again, since we&amp;#039;re updating the item we can omit the item ID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product3&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CurlPut|link|/items/user4/add}}&lt;br /&gt;
&lt;br /&gt;
== Adding a property to an item ==&lt;br /&gt;
&lt;br /&gt;
Sets the value of the property &amp;#039;&amp;#039;country&amp;#039;&amp;#039; to &amp;#039;&amp;#039;Germany&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;country&amp;quot;&amp;gt;Germany&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CurlPut|property|/items/user4/add}}&lt;br /&gt;
&lt;br /&gt;
== Add several tags / properties / links to an item ==&lt;br /&gt;
&lt;br /&gt;
Just like you can add single tags, properties or links to an item, you can also add (or remove) several at a time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;German&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;first name&amp;quot;&amp;gt;Matthias&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;last name&amp;quot;&amp;gt;Schmidt&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product2&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CurlPut|several|/items/user4/add}}&lt;br /&gt;
&lt;br /&gt;
== Removing a tag from an item ==&lt;br /&gt;
&lt;br /&gt;
Just like we could add a tag to an item incrementally, we can remove a tag (or property, or link) by uploading the same content to the &amp;#039;&amp;#039;remove&amp;#039;&amp;#039; sub-resource.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;Berliner&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CurlPut|tag|/items/user4/remove}}&lt;br /&gt;
&lt;br /&gt;
== Removing a link from an item ==&lt;br /&gt;
&lt;br /&gt;
And now we can do the same with removing the link to &amp;#039;&amp;#039;product3&amp;#039;&amp;#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product3&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CurlPut|link|/items/user4/remove}}&lt;br /&gt;
&lt;br /&gt;
== Retrieving an item ==&lt;br /&gt;
&lt;br /&gt;
Now that we&amp;#039;ve made a number of changes to the item that we&amp;#039;ve been working with, let&amp;#039;s see what the current state of it in the database is:&lt;br /&gt;
&lt;br /&gt;
{{CurlGet|/items/user4}}&lt;br /&gt;
&lt;br /&gt;
Produces:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user4&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;German&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;product2&amp;lt;/link&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;first name&amp;quot;&amp;gt;Matthias&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;last name&amp;quot;&amp;gt;Schmidt&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;city&amp;quot;&amp;gt;Berlin&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;country&amp;quot;&amp;gt;Germany&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Deleting an item ==&lt;br /&gt;
&lt;br /&gt;
And now let&amp;#039;s clear out the item we&amp;#039;ve been working with from the database.&lt;br /&gt;
&lt;br /&gt;
{{CurlGet|/items/user4|argument=-X DELETE}}&lt;br /&gt;
&lt;br /&gt;
== Finding related items ==&lt;br /&gt;
&lt;br /&gt;
Let&amp;#039;s get the related items for &amp;#039;&amp;#039;product1&amp;#039;&amp;#039;:&lt;br /&gt;
&lt;br /&gt;
{{CurlGet|/items/product1/related}}&lt;br /&gt;
&lt;br /&gt;
Gives us all related items:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;product1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;related&amp;gt;product2&amp;lt;/related&amp;gt;&lt;br /&gt;
    &amp;lt;related&amp;gt;user1&amp;lt;/related&amp;gt;&lt;br /&gt;
    &amp;lt;related&amp;gt;user3&amp;lt;/related&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hmm, well, that&amp;#039;s not quite what we wanted, but have no fear, this is where the &amp;#039;&amp;#039;tags&amp;#039;&amp;#039; query attribute comes in handy:&lt;br /&gt;
&lt;br /&gt;
{{CurlGet|/items/product1/related\?tags&amp;amp;#61;product}}&lt;br /&gt;
&lt;br /&gt;
And now we get back just items with the &amp;#039;&amp;#039;product&amp;#039;&amp;#039; tag:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;product1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;related&amp;gt;product2&amp;lt;/related&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Doing personalized recommendations ==&lt;br /&gt;
&lt;br /&gt;
Note that when we want to do personalized recommendations we use the &amp;#039;&amp;#039;recommended&amp;#039;&amp;#039; pseudo-resource rather than &amp;#039;&amp;#039;related&amp;#039;&amp;#039;.  Our servers do a little different of a sort of magic for producing personalized recommendations than are used to find related products or pages.&lt;br /&gt;
&lt;br /&gt;
{{CurlGet|/items/user3/recommended}}&lt;br /&gt;
&lt;br /&gt;
Here are the personalized recommendations for &amp;#039;&amp;#039;user3&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user3&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;recommended&amp;gt;user1&amp;lt;/recommended&amp;gt;&lt;br /&gt;
    &amp;lt;recommended&amp;gt;product2&amp;lt;/recommended&amp;gt;&lt;br /&gt;
    &amp;lt;recommended&amp;gt;product1&amp;lt;/recommended&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But here we also get a user in the result set &amp;amp;mdash; just as above we want to specify the tags that we&amp;#039;re interested in:&lt;br /&gt;
&lt;br /&gt;
{{CurlGet|/items/user3/recommended\?tags&amp;amp;#61;product}}&lt;br /&gt;
&lt;br /&gt;
Which now gives us only product results:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user3&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;recommended&amp;gt;product2&amp;lt;/recommended&amp;gt;&lt;br /&gt;
    &amp;lt;recommended&amp;gt;product1&amp;lt;/recommended&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, now we get just products back, but &amp;#039;&amp;#039;user3&amp;#039;&amp;#039; is already connected to &amp;#039;&amp;#039;product2&amp;#039;&amp;#039; &amp;amp;mdash; meaning we assume that they&amp;#039;ve already purchased or rated it, so we don&amp;#039;t actually want that in the result set.  So let&amp;#039;s throw in the &amp;#039;&amp;#039;excludeLinked=true&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
{{CurlGet|/items/user3/recommended\?tags&amp;amp;#61;product\&amp;amp;excludeLinked&amp;amp;#61;true}}&lt;br /&gt;
&lt;br /&gt;
Now we get only things tagged &amp;#039;&amp;#039;product&amp;#039;&amp;#039; and none of the ones that the user already has a connection to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;item id=&amp;quot;user3&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;recommended&amp;gt;product1&amp;lt;/recommended&amp;gt;&lt;br /&gt;
  &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And there we have the (admittedly short) list of personalized recommendations for &amp;#039;&amp;#039;user3&amp;#039;&amp;#039;.&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/XML_Format</id>
		<title>XML Format</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/XML_Format"/>
				<updated>2009-05-20T05:31:27Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, keeping in mind all of the basic structures from [[API Concepts]], let&amp;#039;s see what they look like in XML.&lt;br /&gt;
&lt;br /&gt;
There are three major cases in which we&amp;#039;ll get or send XML to the Directed Edge [[REST API]]:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Import / Export&amp;#039;&amp;#039;&amp;#039; - this is just a list of all items with all of their links, properties and tags included.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Updates&amp;#039;&amp;#039;&amp;#039; - you can update single items in the database or add or remove links, properties and tags.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Queries&amp;#039;&amp;#039;&amp;#039; - for &amp;#039;&amp;#039;related&amp;#039;&amp;#039; or &amp;#039;&amp;#039;recommended&amp;#039;&amp;#039; items (there&amp;#039;s a difference).&lt;br /&gt;
&lt;br /&gt;
The first two basically have the same form, with the notable difference that imports and exports contain multiple items, whereas updates only contain one item.  Queries contain a list of item identifiers that are related to the query item.&lt;br /&gt;
&lt;br /&gt;
== Import / export example ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;item id=&amp;#039;user_1&amp;#039;&amp;gt;&lt;br /&gt;
  &amp;lt;link&amp;gt;product_1&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;tag&amp;gt;customer&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;#039;last name&amp;#039;&amp;gt;Schmidt&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;#039;first name&amp;#039;&amp;gt;Bob&amp;lt;/property&amp;gt;&lt;br /&gt;
 &amp;lt;/item&amp;gt;&lt;br /&gt;
 &amp;lt;item id=&amp;#039;product_1&amp;#039;&amp;gt;&lt;br /&gt;
  &amp;lt;tag&amp;gt;product&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;#039;artist&amp;#039;&amp;gt;Beatles&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;#039;name&amp;#039;&amp;gt;White Album&amp;lt;/property&amp;gt;&lt;br /&gt;
 &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we&amp;#039;ve got a customer, named &amp;#039;&amp;#039;Bob Schmidt&amp;#039;&amp;#039; that&amp;#039;s connected to an album called &amp;#039;&amp;#039;The White Album&amp;#039;&amp;#039; by &amp;#039;&amp;#039;Beatles&amp;#039;&amp;#039;.  So we&amp;#039;ve got two [[item]]s and one [[link]].  Let&amp;#039;s start breaking this down a little.&lt;br /&gt;
&lt;br /&gt;
If you imported this to your Directed Edge account using the [[REST API]], you&amp;#039;d have a database with two items.  Similarly, if you requested a database export right after that, this is what you&amp;#039;d get back.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Before you start sending XML to our server, we recommend passing it through [http://www.xmlsoft.org/xmllint.html xmllint] or similar to make sure that the XML is valid.&amp;#039;&amp;#039;&amp;#039;  The most common problem that we see with users that are new to the API is sending invalid XML and then our servers choking on it.&lt;br /&gt;
&lt;br /&gt;
== Related / recommended query example ==&lt;br /&gt;
&lt;br /&gt;
: &amp;#039;&amp;#039;Results for things related to &amp;quot;Web 2.0&amp;quot; in our Wikipedia database&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;item id=&amp;quot;Web 2.0&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;related&amp;gt;Ajax (programming)&amp;lt;/related&amp;gt;&lt;br /&gt;
  &amp;lt;related&amp;gt;Delicious (website)&amp;lt;/related&amp;gt;&lt;br /&gt;
  &amp;lt;related&amp;gt;Flickr&amp;lt;/related&amp;gt;&lt;br /&gt;
  &amp;lt;related&amp;gt;Web service&amp;lt;/related&amp;gt;&lt;br /&gt;
  &amp;lt;related&amp;gt;RSS&amp;lt;/related&amp;gt;&lt;br /&gt;
 &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The result structure here is pretty self-explanatory &amp;amp;mdash; the item is the one which was queried for and the list of results contains the identifiers of the related items.  Here, notably, the order is important.  Items near the top of the list rank higher than items further down.&lt;br /&gt;
&lt;br /&gt;
The only difference in the XML between an &amp;#039;&amp;#039;related&amp;#039;&amp;#039; and &amp;#039;&amp;#039;recommended&amp;#039;&amp;#039; query is the name of the element that the results are wrapped in.&lt;br /&gt;
&lt;br /&gt;
== Update examples ==&lt;br /&gt;
&lt;br /&gt;
: &amp;#039;&amp;#039;Do a complete update on the item user_1&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;item id=&amp;#039;user_1&amp;#039;&amp;gt;&lt;br /&gt;
  &amp;lt;link&amp;gt;product_1&amp;lt;/link&amp;gt;&lt;br /&gt;
  &amp;lt;tag&amp;gt;customer&amp;lt;/tag&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;#039;last name&amp;#039;&amp;gt;Schmidt&amp;lt;/property&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;#039;first name&amp;#039;&amp;gt;Bob&amp;lt;/property&amp;gt;&lt;br /&gt;
 &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the same format as we used for an import except that there&amp;#039;s only one item.  As noted in the [[REST API]] if this is PUT to an item it will overwrite all existing data.&lt;br /&gt;
&lt;br /&gt;
: &amp;#039;&amp;#039;Add or remove the tag &amp;quot;user&amp;quot; from an item&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;item&amp;gt;&lt;br /&gt;
  &amp;lt;tag&amp;gt;user&amp;lt;/tag&amp;gt;&lt;br /&gt;
 &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is basically just a snippet from a usual item.  One notable difference is that the item id may (but doesn&amp;#039;t have to be) omitted for updating an item (using the add or remove methods noted in the API docs).&lt;br /&gt;
&lt;br /&gt;
: &amp;#039;&amp;#039;Remove the property &amp;quot;last name&amp;quot; from an item&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;item&amp;gt;&lt;br /&gt;
  &amp;lt;property name=&amp;quot;last name&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;
 &amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/directededge&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similar to adding a tag, when removing a property it&amp;#039;s worth noting that the value of the property is completely ignored.&lt;br /&gt;
&lt;br /&gt;
== XML header ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Good old garden variety [[Wikipedia:XML|XML]] header.  We prefer UTF-8, but we shouldn&amp;#039;t blow up if you send us other stuff.&lt;br /&gt;
&lt;br /&gt;
== directededge element ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;directededge version=&amp;quot;0.1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nothing too exotic here for the moment.  This wraps up all of the stuff that you&amp;#039;ll send our receive for the moment.  Version is always &amp;#039;&amp;#039;0.1&amp;#039;&amp;#039; for the moment because, well, we&amp;#039;re too lazy to bump the version.  (Though we&amp;#039;ll do better versioning once we&amp;#039;re out of beta.)&lt;br /&gt;
&lt;br /&gt;
== item element ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;item id=&amp;#039;user_1&amp;#039;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An item is the container for all of the stuff in our database.  Exactly what items are is explained in [[API Concepts]].&lt;br /&gt;
&lt;br /&gt;
=== id attribute ===&lt;br /&gt;
&lt;br /&gt;
Every item &amp;#039;&amp;#039;must&amp;#039;&amp;#039; have an id attribute.  That&amp;#039;s the handle that we use to refer to the item everywhere.  If you want to update or delete the item, you refer to it by its &amp;#039;&amp;#039;id&amp;#039;&amp;#039;.  You can use any scheme that you want to for creating item identifiers, so long as they&amp;#039;re unique.  Often something like &amp;#039;&amp;#039;type&amp;#039;&amp;#039;_&amp;#039;&amp;#039;number&amp;#039;&amp;#039; is convenient.&lt;br /&gt;
&lt;br /&gt;
== tag element ==&lt;br /&gt;
&lt;br /&gt;
Tags are always a child element of an &amp;#039;&amp;#039;item&amp;#039;&amp;#039;.  Tags can be free form as well.  Usually they&amp;#039;re things like &amp;#039;&amp;#039;user&amp;#039;&amp;#039;, &amp;#039;&amp;#039;product&amp;#039;&amp;#039;, &amp;#039;&amp;#039;page&amp;#039;&amp;#039;, but they can also be much more specific like, &amp;#039;&amp;#039;artist&amp;#039;&amp;#039;, &amp;#039;&amp;#039;album&amp;#039;&amp;#039;, &amp;#039;&amp;#039;sci-fi&amp;#039;&amp;#039;, etc.  You can associate as many tags as you would like with a particular item.&lt;br /&gt;
&lt;br /&gt;
== property element ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;property name=&amp;#039;last name&amp;#039;&amp;gt;Schmidt&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Properties are a set of key-value pairs associate with an item.  Again, they are free form.  You don&amp;#039;t need to insert all of the values that you store locally in your database, in fact, most of the time you don&amp;#039;t need to associate any at all.  These are only useful if you later would like to grab data from the Directed Edge [[REST API]] about the items that you&amp;#039;re storing there.  You can associate as many properties with an item as you like, so long as their names are unique.&lt;br /&gt;
&lt;br /&gt;
=== name attribute ===&lt;br /&gt;
&lt;br /&gt;
Every property &amp;#039;&amp;#039;must&amp;#039;&amp;#039; have a name attribute.  This can be anything that you like, but there may only be one property with a given name per item.&lt;br /&gt;
&lt;br /&gt;
== link element ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;link&amp;gt;product_1&amp;lt;/link&amp;gt;&lt;br /&gt;
&amp;lt;link weight=&amp;quot;3&amp;quot;&amp;gt;product_2&amp;lt;/link&amp;gt;&lt;br /&gt;
&amp;lt;link type=&amp;quot;purchase&amp;quot;&amp;gt;product_3&amp;lt;/link&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The link element, surprise, surprise &amp;amp;mdash; indicates a link between two items.  The identifiers used in the text, here &amp;#039;&amp;#039;product_1&amp;#039;&amp;#039;, &amp;#039;&amp;#039;product_2&amp;#039;&amp;#039;, and &amp;#039;&amp;#039;product_3&amp;#039;&amp;#039; are just the IDs of items in the database.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Links to items that do not exist will be ignored unless those items are defined in the same import.&amp;#039;&amp;#039;&amp;#039;  In other words, if you have a link to an item that&amp;#039;s defined lower in the same batch of XML, no problemo.  But if you create a dead link, that just gets ignored.&lt;br /&gt;
&lt;br /&gt;
=== weight attribute ===&lt;br /&gt;
&lt;br /&gt;
The weight attribute is what we use for stuff like rankings.  Weights can be in the range of 1 to 10 (or zero if you want to explicitly say there&amp;#039;s no weight).&lt;br /&gt;
&lt;br /&gt;
So, if we want to say &amp;#039;&amp;#039;user_1 gave product_1 a rating of 5&amp;#039;&amp;#039; that looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;item id=&amp;quot;user_1&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;link weight=&amp;quot;5&amp;quot;&amp;gt;product_1&amp;lt;/link&amp;gt;&lt;br /&gt;
&amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== type attribute ===&lt;br /&gt;
&lt;br /&gt;
This specifies a type for the link.  &amp;#039;&amp;#039;Link types&amp;#039;&amp;#039; can be imagined as a set of graphs superimposed upon each other.  For example, in an e-commerce settings, these could be &amp;#039;&amp;#039;purchased&amp;#039;&amp;#039;, &amp;#039;&amp;#039;rated&amp;#039;&amp;#039;, &amp;#039;&amp;#039;category&amp;#039;&amp;#039;, etc.&lt;br /&gt;
&lt;br /&gt;
You can then mix and match these &amp;#039;&amp;#039;types&amp;#039;&amp;#039; in recommendations &amp;amp;mdash; for example if you wanted to show related products based mostly on purchase, but also considering category information, you can specify that at query time.  See our [[REST API]] for details on how to query link types.&lt;br /&gt;
&lt;br /&gt;
So, if we want to say &amp;#039;&amp;#039;user_1 purchaseds product_1 and product_2 gave product_1 a rating of 5&amp;#039;&amp;#039; that looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;item id=&amp;quot;user_1&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;link type=&amp;quot;purchase&amp;quot;&amp;gt;product_1&amp;lt;/link&amp;gt;&lt;br /&gt;
 &amp;lt;link type=&amp;quot;purchase&amp;quot;&amp;gt;product_2&amp;lt;/link&amp;gt;&lt;br /&gt;
 &amp;lt;link type=&amp;quot;rating&amp;quot; weight=&amp;quot;5&amp;quot;&amp;gt;product_1&amp;lt;/link&amp;gt;&lt;br /&gt;
&amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;#039;&amp;#039;weights&amp;#039;&amp;#039; vs. &amp;#039;&amp;#039;types&amp;#039;&amp;#039; ===&lt;br /&gt;
&lt;br /&gt;
There is both a semantic and practical different between weights and types.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Weights&amp;#039;&amp;#039;&amp;#039; are used to represent things that are intrinsic to the data, but where the links being related are categorically similar.  Ratings would be one notable example, repeat purchases would be another.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Types&amp;#039;&amp;#039;&amp;#039; are used to specify different categories of relationships.  For things that are categorically different, types have the advantage that they may be mixed and matched at query time rather than needing to be encoded, as with weights, at the time the data is uploaded to our service.&lt;br /&gt;
&lt;br /&gt;
== preselected element ==&lt;br /&gt;
&lt;br /&gt;
This is a simple way to specify that another item should always appear in the recommendations returned for this item.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;preselected&amp;gt;product_1&amp;lt;/preselected&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== blacklisted element ==&lt;br /&gt;
&lt;br /&gt;
This is a simple way to specify that another item should never appear in the recommendations returned for this item.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;blacklisted&amp;gt;product_1&amp;lt;/blacklisted&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== related element ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;related&amp;gt;user_1&amp;lt;/related&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Totally no frills.  Results from a &amp;#039;&amp;#039;related&amp;#039;&amp;#039; items query.  Order matters.&lt;br /&gt;
&lt;br /&gt;
== recommended element ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;recommended&amp;gt;product_1&amp;lt;/recommended&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same deal as the related element, but for the results of &amp;#039;&amp;#039;recommended&amp;#039;&amp;#039; queries.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Web Services Examples]]&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/Introduction_to_Recommendations</id>
		<title>Introduction to Recommendations</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/Introduction_to_Recommendations"/>
				<updated>2009-05-20T01:26:43Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;: &amp;#039;&amp;#039;This is a reprint from an article by Directed Edge co-founder Scott Wheeler that originally appeared in two parts in Gründerszene ([http://www.gruenderszene.de/it/we-think-youd-also-like-and-the-math-of-suggestion-–-teil-1/ Part 1], [http://www.gruenderszene.de/it/we-think-youd-also-like-and-the-math-of-suggestion-teil-2/ Part 2])&lt;br /&gt;
&lt;br /&gt;
I still buy vinyl records. There’s something nostalgic about friction between a needle and wax producing my music in the age of iTunes. When I buy records I don’t go to one of the Kreuzberg outlets near to where I live, I go across town to Rotation Records. Why? Because of Niko.&lt;br /&gt;
&lt;br /&gt;
Niko owns Rotation and his knowledge of the the genres that he stocks make it worth taking 90 minutes out of my day to get his input. Niko doesn’t know who I am, but if I ask and tell him a little about the records I’ve bought in the past, he can get a pretty good idea of what I might be interested in. It’s in his interest to know his stuff - it makes his customers buy more records and keeps them coming back to Rotation.&lt;br /&gt;
&lt;br /&gt;
Recommendations have no doubt been a component of sales since the advent of commerce. But we do live in the age of iTunes, the age of Amazon, where millions of products are stored in far away warehouses and shipped through complicated, automated logistics. So, who is the “Niko” in the world of e-commerce?&lt;br /&gt;
&lt;br /&gt;
[[Image:Amazon-recommendations.png]]&lt;br /&gt;
&lt;br /&gt;
Amazon was one of the pioneers in the use of automatic recommendations to drive sales. $5 billion, or 25% of the annual sales come from suggesting products to users by showing related books or personalized music recommendations. iTunes’ “Genius” suggests music downloads and Last.fm’s recommender system builds personalized radio streams and shows related concerts. Berlin is home to at least three startups focusing on different elements of recommendations: Plista’s web personalization, Mufin’s music analysis and my own startup, Directed Edge’s, pluggable recommendations offered as a web-service.&lt;br /&gt;
&lt;br /&gt;
But aside from large e-commerce sites and startups that themselves are focusing on recommendations, how are recommendations relevant to the larger startup world? In a survey by ChoiceStream in 2007, 45% of users surveyed were found to be more likely to shop at a store that provided product recommendations, and for users that spent more than $1,000 online in the previous six months, the number went up to a full 69%. The same survey showed that 41% of users were more likely to pay attention to advertising that was personalized to their tastes. In social media and news sites recommendations reduce bounce rates by showing related content within the site.&lt;br /&gt;
&lt;br /&gt;
So that’s the “why”, now what about the “how?”&lt;br /&gt;
&lt;br /&gt;
== Collaborative Filtering ==&lt;br /&gt;
&lt;br /&gt;
Collaborative filtering is the best known branch of recommender systems. In non-computer scientist terms it just means looking at histories of ratings, purchases and clicks and figuring out which products or users are similar to each other based on that.&lt;br /&gt;
&lt;br /&gt;
Let’s imagine that Bob and Sarah have both given ratings to “The Art of the Start” and “Information Rules”.&lt;br /&gt;
&lt;br /&gt;
[[Image:ratings.png]]&lt;br /&gt;
&lt;br /&gt;
If we want to figure out how similar Bob and Sarah’s tastes are, we can plot their ratings on a graph:&lt;br /&gt;
&lt;br /&gt;
[[Image:user-based.png]]&lt;br /&gt;
&lt;br /&gt;
If we recall a little school geometry, we can figure out how far apart their tastes are. (You do remember the Pythagorean theorem, don’t you?)&lt;br /&gt;
&lt;br /&gt;
[[Image:l2-norm.png]]&lt;br /&gt;
&lt;br /&gt;
In linear algebra, the branch of mathematics that dominates collaborative filtering, is called the “euclidean norm” and is one of the simplest ways to measure how far apart two users’ tastes are. If we were to add a third user, Josh, and computed his distance from Bob and Sarah, we could say, “Josh’s taste is closer to Sarah’s than to Bob’s”.&lt;br /&gt;
&lt;br /&gt;
In practice, these systems aren’t computed for two or three users and two books, they’re computed for hundreds, thousands, or even millions of products and users. But let’s keep things simple: If we had measured the distance between Bob and every other user in an online store, we could then say, “Here are the 10 users closest to Bob.” And from there we have a basis for delivering recommendations. There’s a pretty good chance that Bob will like some of the books that those other 10 people like him have purchased and that he doesn’t own yet.&lt;br /&gt;
&lt;br /&gt;
But there’s a catch.&lt;br /&gt;
&lt;br /&gt;
You see, every time a new book is added to the set of ratings above, a new dimension is added to the computations. Two books, two dimensions; three books, three dimensions; a million books, a million dimensions. And if there were 100,000 books and 100,000 users, measuring the distance between each user would take at least 15 billion mathematical operations. In computer science, that computation is said to scale “quadratically”. In practical terms, it means just throwing more hardware at the problem won’t make it scale.&lt;br /&gt;
&lt;br /&gt;
Because of the computational limitations of user-based collaborative filtering, around 2001 there was a shift to what’s known as “item-based collaborative filtering”. In item based collaborative filtering, instead of first finding related users and then using those users to find related products or content, item-based strategies first compute the similarity of every item and use that to recommend products.&lt;br /&gt;
&lt;br /&gt;
Let’s take the ratings above, but add a third book, “Blue Ocean Strategy” and assume that Bob gave it a rating of 5 and Sarah a rating of 7.&lt;br /&gt;
&lt;br /&gt;
[[Image:item-based.png]]&lt;br /&gt;
&lt;br /&gt;
Now, instead of seeing how similar Bob and Sarah are, we see how similar each product is to the others. To deliver recommendations for Bob we can then see which product he’s liked and jump to products which are similar to those.&lt;br /&gt;
&lt;br /&gt;
Item-based collaborative filtering works well when the set of items, or products, is fairly static and smaller than the number of users, as is typical in an online store. The advantage of item-based strategies is that we can quickly compute recommendations for Bob without having to first compare him to every other user of the store. If Bob has rated 100 items, we can look at his top 10 highest rated items, find the items related to those that he hasn’t purchased and rank them based on how similar they are to his top 10.&lt;br /&gt;
&lt;br /&gt;
To do this, however, item-based collaborative filtering requires a pre-processing step where the similarity of every product is first computed. Even some of the big names in collaborative filtering - Amazon, Last.fm, for instance - until recently didn’t update their recommendations more often than every few days or once a week because computing the item similarity matrix takes so long.&lt;br /&gt;
&lt;br /&gt;
The complexity of this computation is the same as creating user-based recommendations; it’s the same 15 billion mathematical operations. One of the most active areas of recommendations research, and one of the defining characteristics of commercial recommender systems, is mitigating this, “curse of dimensionality”, as some papers call it, a problem common to collaborative filtering, image processing and natural language processing.&lt;br /&gt;
&lt;br /&gt;
== Graph-Based Recommendations ==&lt;br /&gt;
&lt;br /&gt;
In computer science lingo, a graph is just a set of connections between things. Those connections are called “edges”. A “directed edge” is a link from one item to another, like a link from one web page to another, and the term my company’s name comes from. One of the most well known applications of graph theory is used in Google’s PageRank, since it ranks the importance of pages based on who links to them and what they link to.&lt;br /&gt;
&lt;br /&gt;
Let’s imagine a small set of friends in a social network:&lt;br /&gt;
&lt;br /&gt;
[[Image:graph.png]]&lt;br /&gt;
&lt;br /&gt;
Bob is a friend of Sarah, and Sarah is a friend of Amy, who is a friend of Josh. Peter is friends with both Amy and Josh. Intuitively, we can guess that Peter and Sarah might get along well since they share some common friends, even though there’s no explicit connection between them.&lt;br /&gt;
&lt;br /&gt;
Graph-based recommendation systems are a less widely known subfield of recommender systems, but they deliver recommendations based on the connections between people or products.  For the mathematically inclined, it can be shown that you in fact can model any traditional collaborative filtering system within a graph. For instance, if we go back to our list of ratings, we can imagine a connection between Bob and “The Art of the Start”. Graph connections, or “edges” can also have weights - meaning, they tell us how strong the connection between those two items is. So Bob has a connection to “The Art of the Start” with a weight of 8, and a connection to “Information Rules” with a weight of 7.&lt;br /&gt;
&lt;br /&gt;
By looking at how strongly Bob is connected to the products in his “neighborhood” of the connection structure, just like we could guess that Peter and Sarah might get along well, we can also guess which products Bob is likely to be interested in. In some cases, graphs provide a way to find more obscure links from people to products because there can be a path from Bob through Peter to, say, “Blue Ocean Strategy”.&lt;br /&gt;
&lt;br /&gt;
When we want to see how similar products are in item-based collaborative filtering, we first have to compare every product to every other product, as noted above. In a graph, we can accomplish the same by stepping back one step in the connection structure, to every user that has bought “Information Rules” and then step forward from each of those users to get a full set of “co-purchased” items. Rather than having to iterate over every product, we can quickly build the set of potential matches and often deliver recommendations in real-time without a batch processing step.&lt;br /&gt;
&lt;br /&gt;
So, those are the foundations of our electronic “Niko” in the digital age.  For a more technical introduction to recommender systems, check out O’Reilly’s Programming Collective Intelligence.&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	<entry>
		<id>https://developer.directededge.com/article/API_Concepts</id>
		<title>API Concepts</title>
		<link rel="alternate" type="text/html" href="https://developer.directededge.com/article/API_Concepts"/>
				<updated>2009-05-19T01:38:11Z</updated>
		
		<summary type="html">&lt;p&gt;Scott: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Directed Edge&amp;#039;s recommendation engine is built on top of our [http://blog.directededge.com/2009/02/27/on-building-a-stupidly-fast-graph-database/ in-house database].  The database works somewhat differently than traditional databases and its interface is our [[REST API]], so it&amp;#039;s useful before getting started to have a feel for how to go about translating things from the way that your site models data to the way that our database works.&lt;br /&gt;
&lt;br /&gt;
== Everything is an item, or &amp;#039;&amp;#039;A brief introduction to schema-less databases&amp;#039;&amp;#039; ==&lt;br /&gt;
&lt;br /&gt;
[[Image:user-item.png|user-item.png]][[Image:product-item.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Users, products, places, web pages &amp;amp;mdash; they&amp;#039;re all items for us.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Really?  Yep.  Above are a couple of examples of things that could be items in our database.&lt;br /&gt;
&lt;br /&gt;
=== Unique Identifiers ===&lt;br /&gt;
&lt;br /&gt;
Items have an identifier (&amp;#039;&amp;#039;user_1&amp;#039;&amp;#039; and &amp;#039;&amp;#039;product_1&amp;#039;&amp;#039; in the example above).  That can&amp;#039;t be changed once it&amp;#039;s imported to the database.  It&amp;#039;s the handle that we use to grab a hold of things later on.  These &amp;#039;&amp;#039;must&amp;#039;&amp;#039; be unique.  Otherwise the database doesn&amp;#039;t know how to tell two items apart.  You can use any scheme that you like to encode these.  Most people just use something like the type of the object (product, for example) and then the numeric ID that&amp;#039;s stored in their SQL database, but you could also use the URL to a page here or anything else that makes sense for your data.&lt;br /&gt;
&lt;br /&gt;
=== Tags ===&lt;br /&gt;
&lt;br /&gt;
Items can also have a collection of text tags.  These are useful in filtering results later on.  If you, for instance, wanted to find all of the books that are recommended for a certain user, it&amp;#039;d be useful to have some items tagged as &amp;#039;&amp;#039;book&amp;#039;&amp;#039;.  You can also give an item as many tags as you want, so it&amp;#039;s no problem to have &amp;#039;&amp;#039;product&amp;#039;&amp;#039;, &amp;#039;&amp;#039;book&amp;#039;&amp;#039; and &amp;#039;&amp;#039;sci-fi&amp;#039;&amp;#039; all associated with the same item.&lt;br /&gt;
&lt;br /&gt;
Note however, that tags are just ways that we can label items; they&amp;#039;re not actively used in finding similar items.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
[[Image:database-table.png|right|250px|]]&lt;br /&gt;
&lt;br /&gt;
Properties are almost as simple.  They&amp;#039;re just a bunch of key-value pairs that are associated with a given item.  Unlike in a traditional database where you&amp;#039;d have a [[Wikipedia:Database schema|schema]] for your users table, another one for your products table and another one for ... well, whatever else you wanted to store, properties in the Directed Edge database are completely ad-hoc.&lt;br /&gt;
&lt;br /&gt;
Just to get the gears turning in your head, examples of things that can be stored in properties are:  price, address, first name, last name, author, etc.  Pretty much all of the standard fare that would go into a database column.&lt;br /&gt;
&lt;br /&gt;
If you&amp;#039;ve got some products that have a property named &amp;#039;&amp;#039;price&amp;#039;&amp;#039; and some that don&amp;#039;t, that&amp;#039;s just fine with us.&lt;br /&gt;
&lt;br /&gt;
At the moment properties aren&amp;#039;t used at all by the recommendations algorithms, but we may add support for doing that later.  For now they&amp;#039;re just a convenient way of keeping tabs on the information that is being recommended.&lt;br /&gt;
&lt;br /&gt;
== Links, or &amp;#039;&amp;#039;the way you connect stuff&amp;#039;&amp;#039; ==&lt;br /&gt;
&lt;br /&gt;
So, we&amp;#039;re huge [[Wikipedia:Graph theory|graph theory]] wonks.  No, no, not like Excel.  Like webs of information.&lt;br /&gt;
&lt;br /&gt;
[[Image:graph.png]]&lt;br /&gt;
&lt;br /&gt;
In computer science lingo, a graph is just a sets of connections between items.  Those connections are called &amp;#039;&amp;#039;edges&amp;#039;&amp;#039; and the items are called &amp;#039;&amp;#039;nodes&amp;#039;&amp;#039;.  All sorts of things can be modeled in graphs, like the way that web pages are connected to each other (there the links between pages are &amp;#039;&amp;#039;edges&amp;#039;&amp;#039;), or as above, a set of friends in a social network.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Let&amp;#039;s make this really easy just to be clear:  &amp;#039;&amp;#039;a graph is just a collection of connected stuff.&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Here&amp;#039;s an example of the two &amp;#039;&amp;#039;items&amp;#039;&amp;#039; from above connected via an &amp;#039;&amp;#039;edge&amp;#039;&amp;#039;.  This would indicate, for instance, that the user had bought that product.&lt;br /&gt;
&lt;br /&gt;
[[Image:user-product-link.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;An &amp;#039;&amp;#039;edge&amp;#039;&amp;#039; is just the math term for what we call a &amp;#039;&amp;#039;link&amp;#039;&amp;#039;.  They&amp;#039;re the connections.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Every &amp;#039;&amp;#039;object&amp;#039;&amp;#039; in the Directed Edge database is an &amp;#039;&amp;#039;item&amp;#039;&amp;#039;; the relationships between them are &amp;#039;&amp;#039;links&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== Examples of links ===&lt;br /&gt;
&lt;br /&gt;
* A &amp;#039;&amp;#039;&amp;#039;user (item) purchases a product (item)&amp;#039;&amp;#039;&amp;#039;, so we make a link from the user to the product.&lt;br /&gt;
* A &amp;#039;&amp;#039;&amp;#039;user (item) gives a rating of 5 to a product (item)&amp;#039;&amp;#039;&amp;#039;, so we create a link between the user and the product with a &amp;#039;&amp;#039;weight&amp;#039;&amp;#039; of 5.&lt;br /&gt;
* A &amp;#039;&amp;#039;&amp;#039;user (item) clicks on a product category (item)&amp;#039;&amp;#039;&amp;#039;, so we make a link from the user to the category page.&lt;br /&gt;
* A &amp;#039;&amp;#039;&amp;#039;user (item) is friends with another user (item)&amp;#039;&amp;#039;&amp;#039;, so we make a link from the user to the other user.&lt;br /&gt;
* A &amp;#039;&amp;#039;&amp;#039;user (item) is a fan of a band (item)&amp;#039;&amp;#039;&amp;#039;, so we make a link from the user to the band.&lt;br /&gt;
* A &amp;#039;&amp;#039;&amp;#039;web page (item) is connected to another web page (item)&amp;#039;&amp;#039;&amp;#039;, so we make a link from the first page to the second page (just mimicking the HTML link structure).&lt;br /&gt;
&lt;br /&gt;
So when getting up and going with the Directed Edge system, you have to decide which bits of information you want to base the recommendations on.&lt;br /&gt;
&lt;br /&gt;
=== Directed edges ===&lt;br /&gt;
&lt;br /&gt;
You notice up there that those arrows aren&amp;#039;t bi-directional?  They don&amp;#039;t have a pointy thing on both sides?  Well, guess where the name of our company comes from:  those are &amp;#039;&amp;#039;directed edges&amp;#039;&amp;#039;.  In graph theory you can have undirected edges and directed edges.  All that &amp;#039;&amp;#039;directed&amp;#039;&amp;#039; means here is that they have a direction.  A connection from &amp;#039;&amp;#039;A&amp;#039;&amp;#039; to &amp;#039;&amp;#039;B&amp;#039;&amp;#039; is not the same as a connection from &amp;#039;&amp;#039;B&amp;#039;&amp;#039; to &amp;#039;&amp;#039;A&amp;#039;&amp;#039;.  One says, &amp;#039;&amp;#039;Bob is a friend of Sarah&amp;#039;&amp;#039; and another implies &amp;#039;&amp;#039;Sarah is a friend of Bob&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
Web page &amp;#039;&amp;#039;A&amp;#039;&amp;#039; can link to web page &amp;#039;&amp;#039;B&amp;#039;&amp;#039; without implying that web page &amp;#039;&amp;#039;B&amp;#039;&amp;#039; also links back to web page &amp;#039;&amp;#039;A&amp;#039;&amp;#039;.  That link is a &amp;#039;&amp;#039;directed edge&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s the same kind of deal when a user buys a product.  We usually want to represent &amp;#039;&amp;#039;a user bought a product&amp;#039;&amp;#039; rather than implying that the product has some sort of fundamental connection with the user (though it might, for instance, if the user was also the author of it).&lt;br /&gt;
&lt;br /&gt;
The only typical use case where this matters in using the API is that if you have friends in a social network, and the friendships are reciprocal (like Facebook) rather than possibly uni-directional (like Twitter), you have to put &amp;#039;&amp;#039;two&amp;#039;&amp;#039; links in there to convey the friendship.&lt;br /&gt;
&lt;br /&gt;
=== Link types ===&lt;br /&gt;
&lt;br /&gt;
We&amp;#039;ve also introduced the notion of &amp;#039;&amp;#039;typed links&amp;#039;&amp;#039;.  &amp;#039;&amp;#039;&amp;#039;Typed links&amp;#039;&amp;#039;&amp;#039; specify something like:&lt;br /&gt;
&lt;br /&gt;
: &amp;#039;&amp;#039;The relationship between this customer and this product is &amp;#039;&amp;#039;&amp;#039;purchase&amp;#039;&amp;#039;&amp;#039;.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Link types can be mixed and matched at query time.&amp;#039;&amp;#039;&amp;#039;  So if you&amp;#039;re asking for &amp;#039;&amp;#039;related products&amp;#039;&amp;#039; you can ask for a mix of recommendations based 80% on purchases and 20% on common tags by saying that you&amp;#039;d like 0.8 of the &amp;#039;&amp;#039;purchase&amp;#039;&amp;#039; link type and 0.2 of the &amp;#039;&amp;#039;tag&amp;#039;&amp;#039; link type.&lt;br /&gt;
&lt;br /&gt;
You can create whatever link types seem appropriate for your site&amp;#039;s data.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Introduction to Recommendations]] for the basics on how recommendations work.&lt;br /&gt;
* [[XML Format]] for information on how to represent these lovely concepts in simple XML.&lt;br /&gt;
* [[REST API]] for documentation on communicating with our webservices.&lt;/div&gt;</summary>
		<author><name>Scott</name></author>	</entry>

	</feed>