Skip to content

Instantly share code, notes, and snippets.

@stefano-bortolotti
Last active May 6, 2022 10:56
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stefano-bortolotti/11316213 to your computer and use it in GitHub Desktop.
Save stefano-bortolotti/11316213 to your computer and use it in GitHub Desktop.
iOS App Rating widget for Dashing

##Preview

Description

Display your iOS App Rating info. It uses iTunes Store website as the source.

##Usage

To use this widget, copy appstore.html, appstore.coffee, and appstore.scss into the /widgets/appstore directory. Put the app_store.rb file in your /jobs folder.

You'll also need the Apple logo. Download it, and put it in your /assets/images folder.

To include the widget in a dashboard, add the following snippet to the dashboard layout file:

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-id="app_store_rating" data-view="Appstore" data-title="iOS Shooping App"></div>
</li>

##Settings

You'll need to set the URL path to your application on the iTunes Store website in the app_store.rb.

appPageUrl = '/gb/app/asos/id457876088' # ASOS Shopping App ID

Rating is fetched every 30 minutes, but you can change that by editing the job schedule.

#!/usr/bin/env ruby
require 'net/http'
require 'openssl'
# Get info from the App Store of your App:
# Last version Average and Voting
# All time Average and Voting
#
# This job will track average vote score and number of votes
# of your App by scraping the App Store website.
# Config
appPageUrl = '/gb/app/asos/id457876088'
SCHEDULER.every '30m', :first_in => 0 do |job|
puts "fetching App Store Rating for App: " + appPageUrl
# prepare request
http = Net::HTTP.new("itunes.apple.com", Net::HTTP.https_default_port())
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # disable ssl certificate check
# scrape detail page of appPageUrl
response = http.request( Net::HTTP::Get.new(appPageUrl) )
if response.code != "200"
puts "App Store store website communication (status-code: #{response.code})\n#{response.body}"
else
data = {
:last_version => {
average_rating: 0.0,
voters_count: 0
},
:all_versions => {
average_rating: 0.0,
voters_count: 0
}
}
# Version: ... aria-label="4 stars, 2180 Ratings"
average_rating = response.body.scan( /(Version(s)?:(.)*?aria-label=[\"\'](?<num>.*?)star)/m )
print "#{average_rating}\n"
# <span class="rating-count">24 Ratings</span>
voters_count = response.body.scan( /(class=[\"\']rating-count[\"\']>(?<num>([\d,.]+)) )/m )
print "#{voters_count}\n"
# all and last versions average rating
if ( average_rating )
if ( average_rating[0] ) # Last Version
raw_string = average_rating[0][0].gsub('star', '')
clean_string = raw_string.match(/[\d,.]+/i)[0]
last_version_average_rating = clean_string.gsub(",", ".").to_f
half = 0.0
if ( raw_string.match(/half/i) )
half = 0.5
end
last_version_average_rating += half
data[:last_version][:average_rating] = '%.1f' % last_version_average_rating
else
puts 'ERROR::RegEx for last version average rating didn\'t match anything'
end
if ( average_rating[1] ) # All Versions
raw_string = average_rating[1][0].gsub('star', '')
clean_string = raw_string.match(/[\d,.]+/i)[0]
all_versions_average_rating = clean_string.gsub(",", ".").to_f
half = 0.0
if ( raw_string.match(/half/i) )
half = 0.5
end
all_versions_average_rating += half
data[:all_versions][:average_rating] = '%.1f' % all_versions_average_rating
else
puts 'ERROR::RegEx for all versions average rating didn\'t match anything'
end
end
# all and last versions voters count
if ( voters_count )
if ( voters_count[0] ) # Last Version
last_version_voters_count = voters_count[0][0].gsub(',', '').to_i
data[:last_version][:voters_count] = last_version_voters_count
else
puts 'ERROR::RegEx for last version voters count didn\'t match anything'
end
if ( voters_count[1] ) # All Versions
all_versions_voters_count = voters_count[1][0].gsub(',', '').to_i
puts all_versions_voters_count
data[:all_versions][:voters_count] = all_versions_voters_count
else
puts 'ERROR::RegEx for all versions voters count didn\'t match anything'
end
end
if defined?(send_event)
send_event('app_store_rating', data)
else
print "#{data}\n"
end
end
end
class Dashing.Appstore extends Dashing.Widget
ready: ->
@onData(this)
onData: (data) ->
widget = $(@node)
console.log(data)
last_version = @get('last_version')
all_versions = @get('all_versions')
rating = last_version.average_rating
console.log(rating)
voters_count = last_version.voters_count
console.log(voters_count)
widget.find('.appstore-rating-value').html( '<div>Last Version Average Rating</div><span id="appstore-rating-integer-value">' + rating + '</span>')
widget.find('.appstore-voters-count').html( '<span id="appstore-voters-count-value">' + voters_count + '</span> Votes' )
widget.find('.appstore-all-versions-average-rating').html( all_versions.average_rating )
widget.find('.appstore-all-versions-voters-count').html( all_versions.voters_count )
<h1 class="title" data-bind="title"></h1>
<div class="appstore-rating-container">
<div class="appstore-rating-value" data-bind='appstore'></div>
<div class="appstore-voters-count" data-bind='appstore'></div>
</div>
<p class="more-info">All versions average Rating <span class="appstore-all-versions-average-rating" data-bind="appstore"></span> - <span class="appstore-all-versions-voters-count" data-bind="appstore"></span> Votes</p>
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #999;
$title-color: #FFF;
// ----------------------------------------------------------------------------
// Widget-comment styles
// ----------------------------------------------------------------------------
.widget-appstore {
background: $background-color url('../assets/apple_logo.png') no-repeat 50% 50%;
.title {
font-weight: bold;
color: $title-color;
opacity: .9
}
.appstore-rating-container {
div > div {
font-size: 24px
}
}
.appstore-rating-value {
font-size: 76px;
#appstore-rating-integer-value {
font-weight: bold;
}
}
.appstore-voters-count {
font-size: 1.5em;
#appstore-voters-count-value {
font-weight: bold
}
}
}
@trnl
Copy link

trnl commented May 15, 2014

@stefano-bortolotti, how about the following?

#!/usr/bin/env ruby
require 'httpclient'
require 'json'

# Get info from the App Store of your App: 
# Last version Average and Voting
# All time Average and Voting
# 
# This job will track average vote score and number of votes  
# of your App by scraping the App Store website.

# Config
APP_ID = '457876088'
APP_COUNTRY = 'gb'

client = HTTPClient.new

SCHEDULER.every '30m', :first_in => 0 do |job|
  res = client.get("http://itunes.apple.com/lookup?id=#{APP_ID}&country=#{APP_COUNTRY}")

  if res.status != 200
    puts "App Store store website communication (status-code: #{res.status})\n#{res.content}"
  else
    data = { 
      :last_version => {
        average_rating: 0.0,
        voters_count: 0
      }, 
      :all_versions => {
        average_rating: 0.0,
        voters_count: 0
      } 
    }
    result = JSON.parse(res.content)['results'][0]

    data[:last_version][:average_rating] = result['averageUserRatingForCurrentVersion']
    data[:last_version][:voters_count] = result['userRatingCountForCurrentVersion']    
    data[:all_versions][:average_rating] = result['averageUserRating']
    data[:all_versions][:voters_count] = result['userRatingCount']      

    send_event('app_store_rating', data)   
  end  
end

@ahanmal
Copy link

ahanmal commented Jun 4, 2014

@trnl Works like a charm!

@edasque
Copy link

edasque commented Oct 22, 2014

Is that just a simplified/cleaner version?

@goris
Copy link

goris commented Nov 27, 2014

@trnl Works amazing and super clean solution. Thanks!

@FlorianBasso
Copy link

It doesn't work for me.
In application.js file, these variables are undefined :

var all_versions, last_version, rating, voters_count, widget;

in the onData() method.

@emoleumassi
Copy link

it doesn't work for me. Nothing is displayed.

@alialamin
Copy link

Hey Stefano, it would be great if this was maintained. I had it running for my previous project a few years back and it worked a treat. Now it no longer works. This is probably related to the Appstore changes.

Anyone have an alternative solution to retrieving App Store ratings for Smashing/Dashing.

@sgoger
Copy link

sgoger commented May 6, 2022

I kind of merged @trnl and @stefano-bortolotti versions to get a working widget. Here's the resulting app_store.rb file:

#!/usr/bin/env ruby
require 'net/http'
require 'uri'
require 'openssl'

# Get info from the App Store of your App: 
# Last version Average and Voting
# All time Average and Voting
# 
# This job will track average vote score and number of votes  
# of your App by scraping the App Store website.

# Config
APP_ID = '457876088'
APP_COUNTRY = 'gb'

SCHEDULER.every '30m', :first_in => 0 do |job|
  uri = URI.parse("https://itunes.apple.com/lookup?id=#{APP_ID}&country=#{APP_COUNTRY}")
  request = Net::HTTP::Get.new(uri)
  request['Accept'] = 'application/json'

  req_options = {
    use_ssl: uri.scheme == 'https',
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end

  if response.code != "200"
    puts "App Store store website communication (status-code: #{response.code})\n#{response.body}"
  else
    data = { 
      :last_version => {
        average_rating: 0.0,
        voters_count: 0
      }, 
      :all_versions => {
        average_rating: 0.0,
        voters_count: 0
      } 
    }
    result = JSON.parse(response.body)['results'][0]

    data[:last_version][:average_rating] = result['averageUserRatingForCurrentVersion']
    data[:last_version][:voters_count] = result['userRatingCountForCurrentVersion']    
    data[:all_versions][:average_rating] = result['averageUserRating']
    data[:all_versions][:voters_count] = result['userRatingCount']      

    send_event('app_store_rating', data)   

  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment