<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/social-networks/</id>
  <link href="https://www.endpointdev.com/blog/tags/social-networks/"/>
  <link href="https://www.endpointdev.com/blog/tags/social-networks/" rel="self"/>
  <updated>2018-05-18T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>Sentiment Analysis with Python</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/05/sentiment-analysis-with-python/"/>
      <id>https://www.endpointdev.com/blog/2018/05/sentiment-analysis-with-python/</id>
      <published>2018-05-18T00:00:00+00:00</published>
      <author>
        <name>Muhammad Najmi bin Ahmad Zabidi</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2018/05/sentiment-analysis-with-python/book-chair-chat-711009-crop.jpg&#34; width=&#34;770&#34; height=&#34;381&#34; alt=&#34;people sitting around a table with smartphone and magazine&#34;&gt;&lt;br&gt;&lt;a href=&#34;https://www.pexels.com/photo/group-of-people-reading-book-sitting-on-chair-711009/&#34;&gt;Photograph by Helena Lopes, CC0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I recently had the chance to spend my weekend enhancing my knowledge by joining a local community meetup in Malaysia which is sponsored by Malaysian Global Innovation &amp;amp; Creativity Centre (MaGIC). The trainer was Mr Lee Boon Kong.&lt;/p&gt;
&lt;h3 id=&#34;anaconda-and-jupyter-notebook&#34;&gt;Anaconda and Jupyter Notebook&lt;/h3&gt;
&lt;p&gt;We started by preparing our Jupyter Notebook setup which is running on the Anaconda Python distribution. The installer is 500 MB in size but pretty handy when we started using it.&lt;/p&gt;
&lt;p&gt;Anaconda comes with a graphical installer called “Navigator” so the user can install some packages for work. However it did not always work for me on some OSes, so I had to use its command-line based tool “conda”. Conda works like Linux-based package management tools such as apt, dnf, yum, and pacman, so to install a package I would just run &lt;code&gt;conda install &amp;lt;package name&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Jupyter uses a web browser to allow us to write the code directly in its cell. It is quite helpful for us to debug the code or if we just want to execute it segment by segment independently.&lt;/p&gt;
&lt;h3 id=&#34;creating-twitters-api-key&#34;&gt;Creating Twitter’s API key&lt;/h3&gt;
&lt;p&gt;First we need to head to &lt;a href=&#34;https://apps.twitter.com/&#34;&gt;apps.twitter.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following items are needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Consumer Key (API key)&lt;/li&gt;
&lt;li&gt;Consumer Secret (API secret)&lt;/li&gt;
&lt;li&gt;Access Token&lt;/li&gt;
&lt;li&gt;Access Token Secret&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;using-tweepy-nltk-and-textblob&#34;&gt;Using Tweepy, NLTK and TextBlob&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;textblob&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; TextBlob
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;tweepy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;nltk&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nltk.download(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;punkt&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nltk.download(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;averaged_perceptron_tagger&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;consumer_token = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;put your token here&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;consumer_secret = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;put your secret here&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;access_token = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;put your access token here&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;access_secret = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;put your access secret here&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;auth = tweepy.OAuthHandler(consumer_token, consumer_secret)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;auth.set_access_token(access_token, access_secret)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;api = tweepy.API(auth)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;public_tweets = api.search(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Avengers Infinity War&amp;#34;&lt;/span&gt;, lang=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;en&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;number of tweets extracted: &amp;#34;&lt;/span&gt; + &lt;span style=&#34;color:#038&#34;&gt;str&lt;/span&gt;(&lt;span style=&#34;color:#038&#34;&gt;len&lt;/span&gt;(public_tweets)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; tweet &lt;span style=&#34;color:#080&#34;&gt;in&lt;/span&gt; public_tweets:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(tweet.text)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    analysis = TextBlob(tweet.text)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(analysis.sentiment)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#04d;background-color:#fff0f0&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we want to increase the number of tweets to be displayed and analyzed, just change this line to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;public_tweets = api.search(&amp;#34;avengers&amp;#34;, count=100, result_type=&amp;#39;recent&amp;#39;, lang=&amp;#39;en&amp;#39;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;analyzing-sentiment-score-results&#34;&gt;Analyzing Sentiment Score Results&lt;/h3&gt;
&lt;p&gt;The sentiment score that we got is summarized as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;lt; 0 - Negative sentiment&lt;/li&gt;
&lt;li&gt;0 - Neutral&lt;/li&gt;
&lt;li&gt;
&lt;blockquote&gt;
&lt;p&gt;0 - Positive sentiment&lt;/p&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By default, the code above uses the English-based library. As a Malaysian, I could not analyze tweets in the Malay language yet. Efforts by the local community are being made to create the Malay-based language corpus for NLTK.&lt;/p&gt;
&lt;h3 id=&#34;looking-at-the-textblob-component&#34;&gt;Looking at the TextBlob Component&lt;/h3&gt;
&lt;p&gt;The Natural Language Processing (NLP) library’s TextBlob did the sentiment processing task.&lt;/p&gt;
&lt;p&gt;I did some reading in &lt;a href=&#34;https://textblob.readthedocs.io/en/dev/&#34;&gt;TextBlob’s documentation&lt;/a&gt;. So for example if I declare:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text = &amp;#39;&amp;#39;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;I love to read!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I get a sentiment polarity value of 0.5 (positive).&lt;/p&gt;
&lt;p&gt;While if I put&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text = &amp;#39;&amp;#39;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;I hate to read!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I get a sentiment polarity value of -1.0 (negative).&lt;/p&gt;
&lt;h3 id=&#34;summary&#34;&gt;Summary&lt;/h3&gt;
&lt;p&gt;Overall I am quite satisfied with what I learned during the session. It is good to have one day spent on a technical workshop like this in which we could be super focused on the content without any external distraction.&lt;/p&gt;
&lt;p&gt;Kudos to Mr Lee for his effort to teach us about data analysis with Python. Till we meet again, hopefully!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Facebook, Twitter, Google&#43; sharing with the URL</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/07/facebook-twitter-google-plus-sharing/"/>
      <id>https://www.endpointdev.com/blog/2014/07/facebook-twitter-google-plus-sharing/</id>
      <published>2014-07-10T00:00:00+00:00</published>
      <author>
        <name>Marina Lohova</name>
      </author>
      <content type="html">
        &lt;p&gt;This blog post is intended for the folks who spent way more time displaying social sharing buttons on their websites than originally planned. My buttons were supposed to bring up the Share Dialog for Facebook, Twitter and Google+ platforms. I had the requirement to display a custom logo and a custom description. It seemed easy&amp;hellip; until it turned out to be rather difficult.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2014/07/facebook-twitter-google-plus-sharing/image-0-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2014/07/facebook-twitter-google-plus-sharing/image-0.png&#34;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;The appropriate format for Twitter is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;a href=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://twitter.com/share?text=&amp;lt;%= desc %&amp;gt;&amp;amp;url=&amp;lt;%= url %&amp;gt;&amp;#34;&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Twitter&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/a&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that Twitter dialog does not include the picture, only the description.&lt;/p&gt;
&lt;p&gt;Trouble started with Facebook when I learned that custom parameters in Facebook’s sharer.php url are officially not supported anymore: &lt;a href=&#34;https://developers.facebook.com/bugs/357750474364812&#34;&gt;https://developers.facebook.com/bugs/357750474364812&lt;/a&gt;. I tried the format widely suggested on forums, and while custom image was successfully displayed, neither title, not description showed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;a href=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://www.facebook.com/sharer.php?u=&amp;lt;%= url %&amp;gt;&amp;amp;p[images][0]=&amp;lt;%= img  %&amp;gt;&amp;amp;description=&amp;lt;%= desc %&amp;gt;&amp;#34;&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Facebook&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/a&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Facebook documentation hinted that addition of the OpenGraph Protocol standard tags to the of the page may help:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;content&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;http://samples.ogp.me/136756249803614&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;property&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;og:url&amp;#34;&lt;/span&gt;/&amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;content&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Chocolate Pecan Pie&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;property&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;og:title&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;content&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;This pie is delicious!&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;property&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;og:description&amp;#34;&lt;/span&gt;/&amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;content&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/851565_496755187057665_544240989_n.jpg&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;property&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;og:image&amp;#34;&lt;/span&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I wasn’t able to get it up and working with sharer.php. After spending considerable amount of time on this I had to give up and acknowledge that the only way to fully customize the dialog would require registering an app and utilizing APP_ID &lt;a href=&#34;https://developers.facebook.com/docs/sharing/reference/share-dialog&#34;&gt;https://developers.facebook.com/docs/sharing/reference/share-dialog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I anticipated the same kind of trouble with the last button for Google+. And I wasn’t mistaken. The only allowed format for G+ is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;a href=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;https://plus.google.com/share?url=&amp;lt;%= url %&amp;gt;&amp;#34;&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Google&lt;/span&gt;+&amp;lt;&lt;span style=&#34;color:#080;background-color:#fff0ff&#34;&gt;/a&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Despite a few mentions on the web this does not work anymore:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;meta content=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;lt;%= desc %&amp;gt;&amp;#34;&lt;/span&gt; itemprop=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Same here. Doesn’t work:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;meta content=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;lt;%= title %&amp;gt;&amp;#34;&lt;/span&gt; property=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;og:title&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;meta content=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;article&amp;#34;&lt;/span&gt; property=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;og:type&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;meta content=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;lt;%= url %&amp;gt;&amp;#34;&lt;/span&gt; property=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;og:url&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;meta content=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;lt;%= img  %&amp;gt;&amp;#34;&lt;/span&gt; property=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;og:image&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;meta content=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;lt;%= desc %&amp;gt;&amp;#34;&lt;/span&gt; property=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;og:description&amp;#34;&lt;/span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Eventually it turned out that it wasn’t possible to use parameters for G+ link unless you sign up for the API key and use one of the API methods. I wasn’t planning to obtain a key at that time, so I had to simply drop the custom logo and text for G+.&lt;/p&gt;
&lt;p&gt;Looks like both Facebook and Google+ took steps to restrict the free usage of their share urls so more people would register their apps with them.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Integrating Facebook SDK and HybridAuth PHP library</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/06/integrating-facebook-sdk-and-hybridauth/"/>
      <id>https://www.endpointdev.com/blog/2014/06/integrating-facebook-sdk-and-hybridauth/</id>
      <published>2014-06-13T00:00:00+00:00</published>
      <author>
        <name>Spencer Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;There are a few different libraries out there for integrating your site with Facebook and other social networking sites. I recently added “Login with Facebook” for a client to their PHP site utilizing the &lt;a href=&#34;https://developers.facebook.com/docs/facebook-login/v2.0&#34;&gt;Facebook JavaScript SDK&lt;/a&gt;. The documentation on Facebook’s site is pretty good (although it could use a few more examples). Beyond just the login feature, this client also wanted to be able to offer a checkbox for “Post a message to Facebook about your order”. And the way they wanted it done required a PHP library to make calls to the Facebook Graph API directly.&lt;/p&gt;
&lt;p&gt;I chose to use the &lt;a href=&#34;https://github.com/hybridauth/hybridauth&#34;&gt;HybridAuth PHP library&lt;/a&gt; which is a wrapper for integrating many different social networking sites using a plugin system (Facebook, Twitter, Google, other OpenID services, etc). Likewise, the docs for HybridAuth were sufficient to get the examples up and running for me. The problem was that none of the examples or documentation fit my scenario, where I already have the login set up and working with the JavaScript SDK but want to utilize the PHP library for posting to a user’s feed.&lt;/p&gt;
&lt;p&gt;When attempting to connect to Facebook with HybridAuth it kept attempting to log the user in again. The main problem was that the access token received from the JavaScript SDK was not getting passed in correctly to HybridAuth, and so it was attempting to get a new access token. The solution I finally got working seems a little dirty (not going through a standard method call or documented API), but it works. Here is the snippet of PHP code to set the Facebook access token so that HybridAuth will use it instead of fetching a new one:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// Connect to Facebook and get the user&amp;#39;s profile
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;try&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#369&#34;&gt;$hybridauth&lt;/span&gt; = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Hybrid_Auth( &lt;span style=&#34;color:#369&#34;&gt;$config&lt;/span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;// Set some session variables needed for HybridAuth
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;        Hybrid_Auth::&lt;span style=&#34;color:#369&#34;&gt;storage&lt;/span&gt;()-&amp;gt;&lt;span style=&#34;color:#369&#34;&gt;set&lt;/span&gt;( &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;hauth_session.facebook.is_logged_in&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Hybrid_Auth::&lt;span style=&#34;color:#369&#34;&gt;storage&lt;/span&gt;()-&amp;gt;&lt;span style=&#34;color:#369&#34;&gt;set&lt;/span&gt;( &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;hauth_session.facebook.token.access_token&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#369&#34;&gt;$_POST&lt;/span&gt;[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;fb_access_token&amp;#39;&lt;/span&gt;] );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#369&#34;&gt;$hybrid_config&lt;/span&gt; = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;$config&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#369&#34;&gt;$fb_config&lt;/span&gt;     = &lt;span style=&#34;color:#369&#34;&gt;$hybrid_config&lt;/span&gt;[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;providers&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;Facebook&amp;#39;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#369&#34;&gt;$fb_app_id&lt;/span&gt;     = &lt;span style=&#34;color:#369&#34;&gt;$fb_config&lt;/span&gt;[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;key&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;id&amp;#39;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#369&#34;&gt;$_SESSION&lt;/span&gt;[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;fb_&amp;#39;&lt;/span&gt;. &lt;span style=&#34;color:#369&#34;&gt;$fb_app_id&lt;/span&gt; .&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;_access_token&amp;#39;&lt;/span&gt;] = &lt;span style=&#34;color:#369&#34;&gt;$_POST&lt;/span&gt;[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;fb_access_token&amp;#39;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#369&#34;&gt;$_SESSION&lt;/span&gt;[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;fb_&amp;#39;&lt;/span&gt;. &lt;span style=&#34;color:#369&#34;&gt;$fb_app_id&lt;/span&gt; .&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;_user_id&amp;#39;&lt;/span&gt;]      = &lt;span style=&#34;color:#369&#34;&gt;$_POST&lt;/span&gt;[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;fb_uid&amp;#39;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;// Now we connect to FB using the given access token for this user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#369&#34;&gt;$adapter&lt;/span&gt;      = &lt;span style=&#34;color:#369&#34;&gt;$hybridauth&lt;/span&gt;-&amp;gt;&lt;span style=&#34;color:#369&#34;&gt;getAdapter&lt;/span&gt;( &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;facebook&amp;#34;&lt;/span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#369&#34;&gt;$user_profile&lt;/span&gt; = &lt;span style=&#34;color:#369&#34;&gt;$adapter&lt;/span&gt;-&amp;gt;&lt;span style=&#34;color:#369&#34;&gt;getUserProfile&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;catch&lt;/span&gt;( Exception &lt;span style=&#34;color:#369&#34;&gt;$e&lt;/span&gt; ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;FB Connection Failed: &amp;lt;b&amp;gt;got an error!&amp;lt;/b&amp;gt; error message=&amp;#39;&lt;/span&gt; . &lt;span style=&#34;color:#369&#34;&gt;$e&lt;/span&gt;-&amp;gt;&lt;span style=&#34;color:#369&#34;&gt;getMessage&lt;/span&gt;() . &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;, error code=&amp;#39;&lt;/span&gt;. &lt;span style=&#34;color:#369&#34;&gt;$e&lt;/span&gt;-&amp;gt;&lt;span style=&#34;color:#369&#34;&gt;getCode&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When a user successfully logs in with the JavaScript SDK, you will be given an authResponse object which contains, among other things, the user’s Facebook ID and an access token. I pass these two values to PHP using an HTTPS ajax call (POST as you can see above). These two values are needed by HybridAuth and stored in certain session variables. These must be set in the session before you call $hybridauth-&amp;gt;getAdapter() method. The order is important, otherwise HybridAuth won’t use the access token you’ve set and will treat the user as not yet logged in.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Respecting API Call Limit with Radian6</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/06/respecting-api-call-limit-with-radian6/"/>
      <id>https://www.endpointdev.com/blog/2012/06/respecting-api-call-limit-with-radian6/</id>
      <published>2012-06-29T00:00:00+00:00</published>
      <author>
        <name>Marina Lohova</name>
      </author>
      <content type="html">
        &lt;p&gt;A common practice in the online API world is to enforce the call limit. Twitter allows 150 API calls per hour. Shopify has 500 API calls per 5 minutes limit. You may learn how to work with Shopify call limit from &lt;a href=&#34;https://web.archive.org/web/20120826132711/http://wiki.shopify.com/Learning_to_Respect_the_API_calls_limit&#34;&gt;this great article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One of our projects was built around interaction with &lt;a href=&#34;http://www.radian6.com/&#34;&gt;Radian6&lt;/a&gt; platform. Radian6 is a new and growing data mining service with the default limit of 100 calls per hour. I will describe our take on the call limit implementation.&lt;/p&gt;
&lt;h3 id=&#34;introducing-the-call-counter&#34;&gt;Introducing the call counter&lt;/h3&gt;
&lt;p&gt;First, we need to know how many calls have been executed in the current hour. Every external call increments the counter field on a special model until the counter reaches the limit. The counter is reset back to zero at the beginning of every hour.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;script/rails g model RadianCallCount&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the migration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;CreateRadianCallCounts&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Migration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;change&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    create_table &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:radian_call_counts&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; |t|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      t.integer &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      t.timestamps
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In db/seeds.rb file&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;puts&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Initializing Radian6 counter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;RadianCallCount&lt;/span&gt;.delete_all
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;RadianCallCount&lt;/span&gt;.create(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:count&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s roll the counter!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rake db:migrate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rake db:seed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;scheduling-the-counter-reset&#34;&gt;Scheduling the counter reset&lt;/h3&gt;
&lt;p&gt;It is necessary to reset the counter back to zero in the beginning of each hour otherwise the subsequent calls will not be executed. The excellent ‘whenever’ gem will take care of this.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gem install whenever
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;cd&lt;/span&gt; your_webapp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wheneverize .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the model:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;RadianCallCount&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;ActiveRecord&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;reset&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;RadianCallCount&lt;/span&gt;.first.update_attribute(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:count&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In config/schedule.rb:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;every &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:hour&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   runner &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;RadianCallCount.reset&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;tracking-call-count&#34;&gt;Tracking call count&lt;/h3&gt;
&lt;p&gt;We will now use the &lt;a href=&#34;https://rubygems.org/gems/rcapture&#34;&gt;rcapture&lt;/a&gt; gem to intercept a call to external API and increment the counter with it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gem install rcapture&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the module containing all Radian-specific methods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;rcapture&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;API_LIMIT&lt;/span&gt; = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;included&lt;/span&gt;(base)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  base.extend &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;RCapture&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Interceptable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  base.capture_pre &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:methods&lt;/span&gt; =&amp;gt; [&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:authenticate&lt;/span&gt;,&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:tweet_stats&lt;/span&gt;] &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; |cs|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;RadianCallCount&lt;/span&gt;.transaction &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      calls_per_hour = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;RadianCallCount&lt;/span&gt;.first.count 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      allowed = (calls_per_hour &amp;lt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Radian&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;API_LIMIT&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      cs.predicate = allowed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      cs.return = &lt;span style=&#34;color:#080&#34;&gt;false&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;RadianCallCount&lt;/span&gt;.first.increment!(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:count&lt;/span&gt;) &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; allowed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code introduces a simple check before ‘authenticate’ and ‘tweets_stats’ methods. If call count exceeds the allowed limit the method is not executed and the method returns &lt;strong&gt;false&lt;/strong&gt;. Otherwise, the counter increments after the successful method execution. We wrap the code in transaction because the actual count in the database may increase while we are making the API_LIMIT comparison.&lt;/p&gt;
&lt;h3 id=&#34;making-the-limit-aware-call&#34;&gt;Making the limit-aware call&lt;/h3&gt;
&lt;p&gt;Everything is ready to make the non-blocking API call. I scheduled a twitter statistics update to run every 3 hours:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;every &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;.hours &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   runner &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Article.tweet_stats&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The non-blocking calls are suitable for most situations. Sometimes there is a need to just keep trying&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;call_with_timeout&lt;/span&gt;(&amp;amp;block)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  timeout = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;.minutes 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  results = &lt;span style=&#34;color:#080&#34;&gt;false&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;while&lt;/span&gt; !results &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    results = block.call
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; !results
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;break&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; timeout &amp;gt;= &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Radian&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;API_MAX_TIMEOUT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Rails&lt;/span&gt;.logger.info(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Sleeping for 5 minutes&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#038&#34;&gt;sleep&lt;/span&gt;(&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Radian&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;API_CALL_TIMEOUT&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      timeout += &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Radian&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;API_CALL_TIMEOUT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  results 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;call_with_timeout { tweet_stats }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That is all for today. Thanks for your attention. Hope the post was useful.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Developing a Spree Application</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/06/developing-spree-application/"/>
      <id>https://www.endpointdev.com/blog/2012/06/developing-spree-application/</id>
      <published>2012-06-15T00:00:00+00:00</published>
      <author>
        <name>Szymon Lipiński</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;a href=&#34;/blog/2012/06/developing-spree-application/image-0-big.jpeg&#34; imageanchor=&#34;1&#34; style=&#34;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&#34;&gt;&lt;img border=&#34;0&#34; height=&#34;320&#34; src=&#34;/blog/2012/06/developing-spree-application/image-0.jpeg&#34; width=&#34;300&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mike Farmer presented one of the projects he worked on. He gave us a very detailed overview of integration of a Spree application into Facebook for a large client.&lt;/p&gt;
&lt;p&gt;He also described the changes that were made in the Spree project to customize it to the client’s needs.&lt;/p&gt;
&lt;p&gt;The most interesting thing in this Spree shop usage is that the company’s clients make extensive use of the admin panel and they can sell their own products for other clients.&lt;/p&gt;
&lt;p&gt;Mike showed us a great overview of writing better Rails applications using better object oriented code along with TDD and extensive SASS usage. He also described the great tools he uses including Screen and Vagrant.&lt;/p&gt;
&lt;p&gt;Mike also talked about the things he learned during working on this project, especially about Spree and Ruby.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Google&#43;</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2011/07/google/"/>
      <id>https://www.endpointdev.com/blog/2011/07/google/</id>
      <published>2011-07-11T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;img border=&#34;0&#34; src=&#34;/blog/2011/07/google/image-0.jpeg&#34; /&gt;
&lt;p&gt;Over the weekend, I dug into Google+ a bit. I wanted to share a few notes about the experience with my coworkers and the world.&lt;/p&gt;
&lt;h3 id=&#34;speed&#34;&gt;Speed&lt;/h3&gt;
&lt;p&gt;Google has done a great job on performance from what I can tell. They’ve followed their own recommendations on optimization by doing things like implementing CSS sprites, caching static assets, and gzipping content. I can’t do performance tests on my authenticated account at &lt;a href=&#34;https://www.webpagetest.org/&#34;&gt;WebPageTest.org&lt;/a&gt;, but the perceived performance is great.&lt;/p&gt;
&lt;h3 id=&#34;user-interface&#34;&gt;User Interface&lt;/h3&gt;
&lt;p&gt;Parts of the user interface look similar to Facebook. But Google deviated from their norm of utilitarian/pragmatic design according to &lt;a href=&#34;https://web.archive.org/web/20110704190022/http://journal.drawar.com/d/engineers-vs-designers/&#34;&gt;this article&lt;/a&gt;, and I appreciate their focus on aesthetics here. This combined with the speed makes for a &lt;strong&gt;delightful&lt;/strong&gt; user experience.&lt;/p&gt;
&lt;h3 id=&#34;circles&#34;&gt;Circles&lt;/h3&gt;
&lt;p&gt;Google offers limited sharing functionality with what they call “Circles”, similar to Facebook groups. In my case, I have the following circles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Friends&lt;/li&gt;
&lt;li&gt;Family&lt;/li&gt;
&lt;li&gt;End Point&lt;/li&gt;
&lt;li&gt;Web People (professional contacts)&lt;/li&gt;
&lt;li&gt;Photography&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Circles are integrated into every part of Google+, which makes it easy to limit posts, photos, videos or other content to individuals or circles. In addition to limiting sharing permissions, you can also limit viewing “Stream” (akin to Facebook’s News Feed) activity to circles; for example, I might only be interested in looking at my “Friends” stream on the weekend, while I might be more inclined to look at my “End Point” stream during the week when I’m in work mode :)&lt;/p&gt;
&lt;h3 id=&#34;conference-calling-or-hangouts&#34;&gt;Conference Calling or “Hangouts”&lt;/h3&gt;
&lt;p&gt;Yesterday, I tried &lt;strong&gt;Google Hangouts&lt;/strong&gt; with a friend from my Windows laptop. I was required to install software on my laptop to run the chat app. Hangouts are similar to Skype video conferencing but are currently limited to 10 people. The quality of the conference call was comparable to Skype and this feature is an obvious competitor to Skype. Skype has always been a bit finicky on Ubuntu, so hangouts will be a clear replacement for me here if it runs smoothly on my Ubuntu laptop(s). I expect the conference calling feature set to grow over time — it’ll be interesting to see what comes out.&lt;/p&gt;
&lt;h3 id=&#34;other-stuff&#34;&gt;Other Stuff&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;/team/jon-jensen/&#34;&gt;Jon&lt;/a&gt; mentioned that the Android app for Google+ is nice. I haven’t examined Sparks much, but it is similar to sharing in Facebook. I also just read that the iPhone app for Google+ is on its way (from a Google+ contact). Finally, I’d consider shifting my photo backups from Flickr to Picasa if future Picasa updates justify the switch, which would allow me to easily share and tag photos, as well as back-up those 2-3 MB photos!&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I’m impressed with the speed and usability of Google+. I’m interested to see the upcoming features &lt;strong&gt;and&lt;/strong&gt; equally as interested to see how much cross-posting is going to happen between Google+ and Facebook, brought up by &lt;a href=&#34;/blog/authors/dave-jenkins/&#34;&gt;Dave Jenkins&lt;/a&gt;, who has also &lt;a href=&#34;https://web.archive.org/web/20120103022906/http://www.davejenkins.com/2011/06/29/early-impressions-of-google/&#34;&gt;written about Google+&lt;/a&gt; after he received an early invite.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Ecommerce Facebook Integration Tips</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2011/02/ecommerce-facebook-integration-tips/"/>
      <id>https://www.endpointdev.com/blog/2011/02/ecommerce-facebook-integration-tips/</id>
      <published>2011-02-23T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;Over the past couple of months, I’ve done quite a bit of Facebook integration work for several clients. All of the clients have ecommerce sites and they share the common goal to improve site traffic and conversion with successful Facebook campaigns. I’ve put together a brief summary of my recent experience.&lt;/p&gt;
&lt;p&gt;First, here are several examples of Facebook integration methods I used:&lt;/p&gt;
&lt;table cellpadding=&#34;10&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;
&lt;tbody&gt;&lt;tr style=&#34;background:#DDE4DF;&#34;&gt;
&lt;th&gt;
Name &amp; Notes
&lt;/th&gt;
&lt;th&gt;
Screenshot Examples
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&#34;top&#34;&gt;
&lt;b&gt;Link to Facebook Page&lt;/b&gt;: This is the easiest integration option. It just requires a link to a Facebook fan page be added to the site.
&lt;/td&gt;
&lt;td align=&#34;center&#34; style=&#34;padding-bottom:30px;&#34; valign=&#34;top&#34;&gt;
&lt;a href=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-0-big.png&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; id=&#34;BLOGGER_PHOTO_ID_5577719060009011122&#34; src=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-0.png&#34; style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 199px; height: 71px;&#34;/&gt;&lt;/a&gt;A link to &lt;a href=&#34;https://www.lotstolivefor.com/&#34;&gt;Lots To Live For’s&lt;/a&gt; Facebook page was added to the header.
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&#34;background:#DDE4DF;&#34;&gt;
&lt;td valign=&#34;top&#34;&gt;
&lt;b&gt;Facebook Like Button&lt;/b&gt;: Implementation of the like button is more advanced than a simple link. Technical details on implementation are discussed below. This was integrated on multiple product page templates. The &#34;like&#34; event and page shows up on the user’s wall.
&lt;/td&gt;
&lt;td align=&#34;center&#34; style=&#34;padding-bottom:30px;&#34; valign=&#34;top&#34;&gt;
&lt;a href=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-1-big.png&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; id=&#34;BLOGGER_PHOTO_ID_5577716422165234146&#34; src=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-1.png&#34; style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 149px;&#34;/&gt;&lt;/a&gt;Like button’s were added throughout &lt;a href=&#34;https://www.papersource.com/&#34;&gt;Paper Source’s&lt;/a&gt; site. The screenshot shown above indicates I’ve liked this product page.&lt;br/&gt;&lt;br/&gt;
&lt;a href=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-2-big.png&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; id=&#34;BLOGGER_PHOTO_ID_5577716422635502162&#34; src=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-2.png&#34; style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 146px;&#34;/&gt;&lt;/a&gt;&#34;Liking&#34; a product page shows up on my facebook wall.
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&#34;top&#34;&gt;
&lt;b&gt;Facebook Like Box&lt;/b&gt;: Another example of Facebook integration is adding a “Like Box”. Acting on the Like Box results in liking the actual Facebook fan page. For example, I added a Like Box to Paper Source’s footer. When a user clicks on it, they are Liking Paper Source’s Facebook page and will begin to receive updates from Paper Source’s Facebook page on their wall.
&lt;/td&gt;
&lt;td align=&#34;center&#34; style=&#34;padding-bottom:30px;&#34; valign=&#34;top&#34;&gt;
&lt;a href=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-3-big.png&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; id=&#34;BLOGGER_PHOTO_ID_5577716667071246818&#34; src=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-3.png&#34; style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 255px; height: 77px;&#34;/&gt;&lt;/a&gt;The Facebook Like Box was added to &lt;a href=&#34;https://www.papersource.com/&#34;&gt;Paper Source’s&lt;/a&gt; footer.&lt;br/&gt;&lt;br/&gt;
&lt;a href=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-4-big.png&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; id=&#34;BLOGGER_PHOTO_ID_5577716660317385122&#34; src=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-4.png&#34; style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 198px;&#34;/&gt;&lt;/a&gt;Clicking on the Like Box is equivalent to liking the Paper Source fan page, shown here.
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&#34;background:#DDE4DF;&#34;&gt;
&lt;td valign=&#34;top&#34;&gt;
&lt;b&gt;Sharer&lt;/b&gt;: The final example of Facebook integration I implemented for a client was adding “sharer” functionality. This is accomplished by adding a link to “http://www.facebook.com/sharer.php?u=” followed by the URI encoded URL. The user is directed to Facebook and allowed to enter an additional comment and select a thumbnail. This is sent to the user’s facebook wall and will be seen in the user’s friends news feeds.
&lt;/td&gt;
&lt;td align=&#34;center&#34; style=&#34;padding-bottom:30px;&#34; valign=&#34;top&#34;&gt;
&lt;a href=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-5-big.png&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; id=&#34;BLOGGER_PHOTO_ID_5577716896731565778&#34; src=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-5.png&#34; style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 263px; height: 48px;&#34;/&gt;&lt;/a&gt;A Facebook share link is displayed for one of our Spree clients.&lt;br/&gt;&lt;br/&gt;
&lt;a href=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-6-big.png&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; id=&#34;BLOGGER_PHOTO_ID_5577716895673012946&#34; src=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-6.png&#34; style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 142px;&#34;/&gt;&lt;/a&gt;When you share an item, you are brought to a page much like the page shown in this screenshot to add a comment or select the thumbnail.&lt;br/&gt;&lt;br/&gt;
&lt;a href=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-7-big.png&#34; onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34;&gt;&lt;img alt=&#34;&#34; border=&#34;0&#34; id=&#34;BLOGGER_PHOTO_ID_5577716895852330578&#34; src=&#34;/blog/2011/02/ecommerce-facebook-integration-tips/image-7.png&#34; style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 148px;&#34;/&gt;&lt;/a&gt;Two of my Facebook friends shared the same article. I saw this on my News Feed.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;In addition to the like button and like box, there are several other types of Facebook plugins including an Activity Feed, Recommendations, Login Button, Facepile, Live Stream, and Comments. Facebook’s documentation on Plugins can be found &lt;a href=&#34;https://developers.facebook.com/docs/plugins/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;plugin-integration-iframe-versus-xfbml&#34;&gt;Plugin Integration: iframe versus xfbml&lt;/h3&gt;
&lt;p&gt;I’ve used iframe integration for the majority of clients and most recently used xfbml for Paper Source. Implementation with an iframe might be easier and require less templates to be modified. Implementation with xfbml provides more flexibility, claims to have more advanced reporting, and allows you to add event listeners to various actions. Here’s a code comparison of equivalent functionality for the two options:&lt;/p&gt;
&lt;table cellpadding=&#34;10&#34; cellspacing=&#34;0&#34; width=&#34;100%&#34;&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th width=&#34;50%&#34;&gt;
iframe
&lt;/th&gt;
&lt;th&gt;
xfbml
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&#34;top&#34;&gt;
&lt;pre class=&#34;brush:plain&#34;&gt;
&lt;iframe
src=&#34;http://www.facebook.com/plugins/like.php
?href=&lt;%= URI.encode(request.url) %&gt;
&amp;layout=button_count&#34;
scrolling=&#34;no&#34; frameborder=&#34;0&#34;
style=&#34;border:none;overflow:hidden;
width:90px;height:21px;&#34;
allowTransparency=&#34;true&#34;&gt;
&lt;/iframe&gt;
&lt;/pre&gt;
&lt;/td&gt;
&lt;td valign=&#34;top&#34;&gt;
&lt;pre class=&#34;brush:plain&#34;&gt;
&lt;p&gt;&lt;fb:like layout=&#34;button_count&#34;&gt;&lt;/fb:like&gt;&lt;/p&gt;
&lt;div id=&#34;fb-root&#34;&gt;&lt;/div&gt;
&lt;script&gt;
var fb_rendered = false;
window.fbAsyncInit = function() {
    FB.init({appId: &#39;*appid*&#39;,
      status: true,
      cookie: true,
      xfbml: true});
};
(function() {
    var e = document.createElement(&#39;script&#39;);
    e.type = &#39;text/javascript&#39;;
    e.src = document.location.protocol +
      &#39;//connect.facebook.net/en_US/all.js&#39;;
    e.async = true;
    document.getElementById(&#39;fb-root&#39;).appendChild(e);
}());
&lt;/script&gt;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&#34;gotchas&#34;&gt;Gotchas&lt;/h3&gt;
&lt;p&gt;Throughout development, I’ve learned a few gotchas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Styling on the Facebook elements is not always easily adjustable. In some cases, the iframe or xfbml element had undesirable styling and the styling of the wrapper div may need to be adjusted to achieve desired results.&lt;/li&gt;
&lt;li&gt;Facebook crawls or scrapes the “Liked” pages to retrieve page information such as a title, description and thumbnail. Facebook follows rel=canonical URLs to retrieve this information—​so it’s important that these canonical URLs are correct. A couple of Paper Source’s product page templates added an extra forward slash to the URL, and these were followed by Facebook’s crawler, resulting in an infinite redirect loop of URLs with additional forward slashes. The result is that Facebook can not scrape the URL and the like button has a flickering effect when clicked.&lt;/li&gt;
&lt;li&gt;Facebook’s crawler caches pages. If there is an error such as the canonical error listed above, it’s recommended to wait 24 hours to test until the page has been re-crawled.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;xmlns, firewall issues&lt;/p&gt;

      </content>
    </entry>
  
</feed>
