<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>140dev &#187; Engagement Programming</title>
	<atom:link href="http://140dev.com/twitter-api-programming-blog/category/engagement-programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://140dev.com</link>
	<description>Twitter API Programming Tips, Tutorials, Source Code Libraries and Consulting</description>
	<lastBuildDate>Wed, 31 Jul 2019 10:03:15 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.6</generator>
		<item>
		<title>Engagement Programming: Best practices for collecting user account info</title>
		<link>http://140dev.com/twitter-api-programming-blog/engagement-programming-best-practices-for-collecting-user-account-info/</link>
		<comments>http://140dev.com/twitter-api-programming-blog/engagement-programming-best-practices-for-collecting-user-account-info/#comments</comments>
		<pubDate>Fri, 29 Nov 2013 14:54:39 +0000</pubDate>
		<dc:creator>Adam Green</dc:creator>
				<category><![CDATA[Engagement Programming]]></category>

		<guid isPermaLink="false">http://140dev.com/?p=2546</guid>
		<description><![CDATA[The Twitter API provides two requests for user account info: users/show and users/lookup. On the surface the difference between the two seems obvious. Users/lookup returns data on 100 accounts at a time, while users/show only delivers a single user. The Twitter docs make the correct suggestion that users/lookup is best suited for gathering the account [&#8230;]]]></description>
				<content:encoded><![CDATA[<p></p><p>The Twitter API provides two requests for user account info: <a href="https://dev.twitter.com/docs/api/1.1/get/users/show">users/show</a> and <a href="https://dev.twitter.com/docs/api/1.1/get/users/lookup">users/lookup</a>. On the surface the difference between the two seems obvious. Users/lookup returns data on 100 accounts at a time, while users/show only delivers a single user. The Twitter docs make the correct suggestion that users/lookup is best suited for gathering the account info based on a list of user_ids returned by requests like friends/ids and followers/ids. This leaves out an important difference between the possible requests. </p>
<p>Users/lookup only returns accounts that have not been deleted or suspended. If you pass 100 user_ids to this API call, and 10 of them are either deleted or suspended, you only get back data on 90 user accounts. It is up to you to compare the accounts returned with the accounts requested, and decide how to deal with any that are missing from the results. The problem with this is that you can&#8217;t tell which of the missing accounts are deleted or suspended. If an account has been suspended, it will almost certainly become active again in a few days. You may want to save the user_id and try again later to get its data. </p>
<p>Users/show, on the other hand, always returns something when a request is made. If the account is valid, you get the full profile. A 404 error code is returned for deleted accounts, and 403 is returned for suspended users. This makes users/show more informative, but rate limits and performance delays from making multiple requests makes it impractical as a replacement for users/lookup. </p>
<p>I&#8217;ve developed a set of best practices for handling this situation:</p>
<ul>
<li>When gathering data on a list of friends or followers, I first run users/lookup as my first pass. If any user_ids do not return results, I put them into a table along with the date/time of the first lookup. I then process this table&#8217;s contents with users/show. The user_ids that return a 404 are removed from the list. I repeat this processing every 24 hours. The suspended users will eventually reappear, and their ids can be then be removed from this list. </li>
<li>I also maintain lists of users that need to be updated regularly for applications like tweet display or suggested follows. I add a date/time field to these user tables that is updated whenever I get a new copy of the account profile. Users/lookup is run against this list every 24 hours or so. If an account hasn&#8217;t been updated for 24 hours, I test it with users/show. Deleted accounts are removed, and suspended accounts are left in place, but flagged as suspended to keep them from being displayed by my apps. </li>
</ul>
<p>You can find <a href="http://140dev.com/twitter-api-engagement-programming/source-code/?script=collect_account_profiles.php">examples</a> of this type of programming in the <a href="http://140dev.com/twitter-api-engagement-programming/source-code/">source code</a> for my <a href="http://www.amazon.com/gp/product/0989875806">engagement programming book</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://140dev.com/twitter-api-programming-blog/engagement-programming-best-practices-for-collecting-user-account-info/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Engagement Programming: Super simple rate limit programming</title>
		<link>http://140dev.com/twitter-api-programming-blog/engagement-programming-super-simple-rate-limit-programming/</link>
		<comments>http://140dev.com/twitter-api-programming-blog/engagement-programming-super-simple-rate-limit-programming/#comments</comments>
		<pubDate>Mon, 25 Nov 2013 13:16:31 +0000</pubDate>
		<dc:creator>Adam Green</dc:creator>
				<category><![CDATA[Engagement Programming]]></category>
		<category><![CDATA[Rate Limits]]></category>

		<guid isPermaLink="false">http://140dev.com/?p=2526</guid>
		<description><![CDATA[Rate limits are a constant concern when doing engagement programming with the REST API. I&#8217;ve settled on an incremental approach. Instead of building a rate accounting infrastructure that measures the remaining requests for each API call, I find it easier to write scripts that break high-usage tasks into manageable chunks that won&#8217;t exceed the limits. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p></p><p><strong>Rate limits</strong> are a constant concern when doing <strong>engagement programming</strong> with the REST API.  I&#8217;ve settled on an incremental approach. Instead of building a rate accounting infrastructure that measures the remaining requests for each API call, I find it easier to write scripts that break high-usage tasks into manageable chunks that won&#8217;t exceed the limits. I then schedule a cronjob to repeat these scripts at a frequency that will stay below the rate limit. If for some reason I get back a 429 error code that signifies an exceeded rate limit, I have the script exit and let it try again later based on the cronjob schedule. </p>
<p>To support this code, I also record all API calls in an api_log database table that saves the account I was working with, the API request made, and the http code returned. A separate script checks this table and emails me if the number of rate limit errors over the last hour exceeds a pre-defined level. </p>
<p>This decoupled approach allows multiple scripts to overlap with the same API call. This is the reality of a complex system. Trying to be too much of a control freak, and coordinate all my scripts to prevent ever hitting a rate limit ends up in diminishing returns. You end up spending more time on the scaffolding surrounding your code, and less on actually getting work done. </p>
<p>Some people are afraid of ever triggering a rate limit error out of fear of suspension, but I have never had that problem. Remember, I back off as soon as I get the first error response. My code monitoring the api log also warns me if my system is getting overloaded. I can then reschedule the cronjobs at a lower rate, or have each script make fewer requests in each cycle. </p>
<p id="ttext">I learned how to manage Twitter API rate limits with a minimum of work. </a></p>
]]></content:encoded>
			<wfw:commentRss>http://140dev.com/twitter-api-programming-blog/engagement-programming-super-simple-rate-limit-programming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Engagement Programming: Leaders will point to your engagement targets</title>
		<link>http://140dev.com/twitter-api-programming-blog/engagement-programming-leaders-will-point-to-your-engagement-targets/</link>
		<comments>http://140dev.com/twitter-api-programming-blog/engagement-programming-leaders-will-point-to-your-engagement-targets/#comments</comments>
		<pubDate>Fri, 22 Nov 2013 14:00:11 +0000</pubDate>
		<dc:creator>Adam Green</dc:creator>
				<category><![CDATA[Engagement Programming]]></category>

		<guid isPermaLink="false">http://140dev.com/?p=2481</guid>
		<description><![CDATA[In yesterday&#8217;s post I recommended searching for the screen names of influential accounts as a way of getting high-quality leads for engagement. A related approach is to collect the timelines of key accounts, and extract the people they @mention. This is a good way to find the cool crowd in any subject area. If a [&#8230;]]]></description>
				<content:encoded><![CDATA[<p></p><p>In <a href="http://140dev.com/twitter-api-programming-blog/engagement-programming-follow-leaders-for-great-following-leads">yesterday&#8217;s post</a> I recommended searching for the screen names of influential accounts as a way of getting high-quality leads for engagement. A related approach is to collect the timelines of key accounts, and extract the people they @mention. This is a good way to find the cool crowd in any subject area. If a leader engages directly with someone, they are worth checking out. You can find code for collecting the <a href="http://140dev.com/twitter-api-engagement-programming/source-code/?script=collect_old_leader_timeline.php">past timeline tweets</a> for any account, and then <a href="http://140dev.com/twitter-api-engagement-programming/source-code/?script=collect_new_leader_timeline.php">updating this collection</a> on a regular basis in my <a href="http://www.amazon.com/Twitter-Engagement-Programming-MySQL-Greens/dp/0989875806/">engagement book</a>&#8216;s source code. </p>
<p>Once you have a leader account&#8217;s tweets collected along with all their @mentions, you can run SQL queries to extract the most mentioned accounts, such as:<br />
SELECT COUNT( * ) AS cnt, users.*<br />
FROM tweet_mentions, users<br />
WHERE tweet_mentions.source_user_id IN<br />
    (SELECT user_id FROM leaders)<br />
AND tweet_mentions.target_user_id = users.user_id<br />
GROUP BY tweet_mentions.target_user_id<br />
ORDER BY cnt DESC </p>
<p>This query assumes that you have recorded the user ids of leader accounts in their own table.</p>
]]></content:encoded>
			<wfw:commentRss>http://140dev.com/twitter-api-programming-blog/engagement-programming-leaders-will-point-to-your-engagement-targets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Engagement Programming: Follow leaders for great following leads</title>
		<link>http://140dev.com/twitter-api-programming-blog/engagement-programming-follow-leaders-for-great-following-leads/</link>
		<comments>http://140dev.com/twitter-api-programming-blog/engagement-programming-follow-leaders-for-great-following-leads/#comments</comments>
		<pubDate>Thu, 21 Nov 2013 11:19:23 +0000</pubDate>
		<dc:creator>Adam Green</dc:creator>
				<category><![CDATA[Engagement Programming]]></category>
		<category><![CDATA[Lead Generation]]></category>

		<guid isPermaLink="false">http://140dev.com/?p=2476</guid>
		<description><![CDATA[A lot of my engagement programming for clients has involved finding good leads for them to build relationships with and gain as followers. Obviously, the search API is a good place to start, but just searching for keywords that match your engagement interests is not the best approach. For example, if I wanted to find [&#8230;]]]></description>
				<content:encoded><![CDATA[<p></p><p>A lot of my engagement programming for clients has involved finding good leads for them to build relationships with and gain as followers. Obviously, the search API is a good place to start, but just searching for keywords that match your engagement interests is not the best approach. For example, if I wanted to find high quality accounts that talk about food, I could run a search for keywords like food, restaurant, or cooking. Try <a href="https://twitter.com/search?q=food%20OR%20restaurant%20OR%20cooking&#038;src=typd&#038;f=realtime">this search</a> and see how poor the quality of the tweets are. All you can really tell is that these users are probably hungry when they tweeted. </p>
<p>You can get much better results by using the leading accounts for your subject as the search keyword. Compare the results of the previous search with this search based on <a href="https://twitter.com/search?q=%40foodnetwork&#038;src=typd&#038;f=realtime">@FoodNetwork</a>. Now we get people tweeting recipes, discussing cooking shows, and a good mix of celebrity chef accounts. The difference in quality is obvious. The rule is that people who tweet with the screen name of a leading account have a serious and informed interest in the subject. This group should be your starting point for an engagement campaign. </p>
<p>You can do your engagement directly from the search results, but if you want to store the results in a database for later analysis, you can start coding with this <a href="http://140dev.com/twitter-api-engagement-programming/source-code/?script=collect_old_leader_search.php">source code</a> from my <a href="http://www.amazon.com/Twitter-Engagement-Programming-MySQL-Greens/dp/0989875806/">engagement programming book</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://140dev.com/twitter-api-programming-blog/engagement-programming-follow-leaders-for-great-following-leads/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Engagement Programming: User ids are the correct key, not screen names</title>
		<link>http://140dev.com/twitter-api-programming-blog/engagement-programming-user-id/</link>
		<comments>http://140dev.com/twitter-api-programming-blog/engagement-programming-user-id/#comments</comments>
		<pubDate>Wed, 20 Nov 2013 13:49:33 +0000</pubDate>
		<dc:creator>Adam Green</dc:creator>
				<category><![CDATA[Engagement Programming]]></category>

		<guid isPermaLink="false">http://140dev.com/?p=2470</guid>
		<description><![CDATA[When you start programming with the Twitter API, the natural tendency is to identify users in your database and code by their screen name. It seems right, since that is how you identify them when using Twitter. I used to do that too until I found out that users in some communities change their screen [&#8230;]]]></description>
				<content:encoded><![CDATA[<p></p><p>When you start programming with the Twitter API, the natural tendency is to identify users in your database and code by their screen name. It seems right, since that is how you identify them when using Twitter. I used to do that too until I found out that users in some communities change their screen names a lot more than expected. Twitter allows you to change an account&#8217;s screen name and still retain all tweets, friends, followers, etc. associated with the account. So if you&#8217;ve built a relational database of tweet data based on screen names and one of them changes, all your pointers for that user break. The only safe way to identify users is through their account&#8217;s user id. This is assigned when an account is created, and it never changes. </p>
<p>You can see a real-world <a href="http://140dev.com/twitter-api-engagement-programming/source-code/?script=engagement.sql">database schema</a> that follows this model of user ids as the linking value in the source code for my <a href="http://www.amazon.com/Twitter-Engagement-Programming-MySQL-Greens/dp/0989875806/">engagement programming book</a>. The only place the screen name is recorded is in the users table. This field is updated with the current screen name every time my code refreshes the user records. </p>
<p>The only annoying aspect of programming with user ids, is that you will need to do a lookup in your database to convert the user id into a screen name so it can be displayed on web pages or in an app. For example, when I need to deliver tweets for display, I link the tweet to its user as follows:</p>
<p>SELECT tweets.*, users.screen_name<br />
FROM tweets, users<br />
WHERE tweets.user_id = users.user_id</p>
]]></content:encoded>
			<wfw:commentRss>http://140dev.com/twitter-api-programming-blog/engagement-programming-user-id/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
