Technical Spec

Angelo Stavrow edited this page Mar 7, 2018 · 2 revisions

App Store Reviews in Manuscript — Technical Spec

Overview

At its most basic, this integration is essentially a feed reader that fetches an RSS feed of customer reviews for products on the App Store and Mac App Store and, for every new review since the last fetch, creates a case in a defined project/area in the customer’s Manuscript account.

Configuration and first-run

When the integration is first run, it should:

  1. Create a file called .data/config.json and .data/reviews.json;
  2. Fetch a list of projects and areas in the Manuscript account;
  3. Prompt the user for a list of apps (“App ID” values in Apple parlance) for which reviews should be fetched
  4. Store app ID(s) for case creation in .data/config.json
  5. Attempt an initial fetch of the RSS feeds based on the App IDs received in step 3.

Enabling a new integration should create a bot user and fetch its API key in the user’s Manuscript account. API keys are stored in the 🗝️.env file, which Glitch guarantees is secret and not remixable (neither is anything placed in .data, so remixes won’t carry over any configuration or review files — they must be created on first-run).

RSS feed fetching

We could try simply writing our own feed reading mechanism, but there’s already a Node.js module (app-store-reviews) that we might be able to leverage. Whichever method we use, review RSS feeds contain the following information.

There’s some app-specific metadata (using reviews for Per on the Canadian App Store as an example) as the first record under entry:, before the reviews:

{
	"category": {
		"attributes": {
			"im:id": "6002",
			"label": "Utilities",
			"scheme": "https://itunes.apple.com/ca/genre/ios-utilities/id6002?mt=8&uo=2",
			"term": "Utilities"
		}
	},
	"id": {
		"attributes": {
			"im:bundleId": "com.DroppedBits.Per",
			"im:id": "922693504"
		},
		"label": "https://itunes.apple.com/ca/app/per-shop-smart-save-money/id922693504?mt=8&uo=2"
	},
	"im:artist": {
		"attributes": {
			"href": "https://itunes.apple.com/ca/developer/dropped-bits/id907966801?mt=8&uo=2"
		},
		"label": "Dropped Bits"
	},
	"im:contentType": {
		"attributes": {
			"label": "Application",
			"term": "Application"
		}
	},
	"im:image": [
		{
			"attributes": {
				"height": "53"
			},
			"label": "http://is1.mzstatic.com/image/thumb/Purple62/v4/92/6c/bb/926cbb6c-69a8-c493-6c84-e4c514052579/mzm.rpgqrbsy.jpg/53x53bb-85.png"
		},
		{
			"attributes": {
				"height": "75"
			},
			"label": "http://is3.mzstatic.com/image/thumb/Purple62/v4/92/6c/bb/926cbb6c-69a8-c493-6c84-e4c514052579/mzm.rpgqrbsy.jpg/75x75bb-85.png"
		},
		{
			"attributes": {
				"height": "100"
			},
			"label": "http://is1.mzstatic.com/image/thumb/Purple62/v4/92/6c/bb/926cbb6c-69a8-c493-6c84-e4c514052579/mzm.rpgqrbsy.jpg/100x100bb-85.png"
		}
	],
	"im:name": {
		"label": "Per \u2013 Shop smart. Save money."
	},
	"im:price": {
		"attributes": {
			"amount": "0.00000",
			"currency": "CAD"
		},
		"label": "Get"
	},
	"im:releaseDate": {
		"attributes": {
			"label": "February 10, 2015"
		},
		"label": "2015-02-10T04:21:51-07:00"
	},
	"link": {
		"attributes": {
			"href": "https://itunes.apple.com/ca/app/per-shop-smart-save-money/id922693504?mt=8&uo=2",
			"rel": "alternate",
			"type": "text/html"
		}
	},
	"rights": {
		"label": "\u00a9 2015 Dropped Bits, Inc."
	},
	"title": {
		"label": "Per \u2013 Shop smart. Save money. - Dropped Bits"
	}
}

This could give us some interesting metadata to present to the user and/or in the created cases, but for now it lets us at least validate the app related to the feed.

And then, the review entry:

{
	"author": {
		"label": "",
		"name": {
			"label": "MattMontrealCanada"
		},
		"uri": {
			"label": "https://itunes.apple.com/ca/reviews/id23627358"
		}
	},
	"content": {
		"attributes": {
			"type": "text"
		},
		"label": "Slick price per unit calculator!"
	},
	"id": {
		"label": "1144924472"
	},
	"im:contentType": {
		"attributes": {
			"label": "Application",
			"term": "Application"
		}
	},
	"im:rating": {
		"label": "5"
	},
	"im:version": {
		"label": "1.0"
	},
	"im:voteCount": {
		"label": "0"
	},
	"im:voteSum": {
		"label": "0"
	},
	"link": {
		"attributes": {
			"href": "https://itunes.apple.com/ca/review?id=922693504&type=Purple%20Software",
			"rel": "related"
		}
	},
	"title": {
		"label": "Get the most bang for your buck!"
	}
}

Some of the key content we’re looking at here is:

  • id
  • author > name
  • author > uri
  • title
  • im:version
  • im:rating
  • content

There’s also an updated: record indicating when the feed was last fetched. We can only get up to 10 pages of reviews (using a page=n parameter in the URL), but pulling in historical reviews is a non-goal, so that’s probably fine.

Case creation

We’ll leverage the Manuscript JSON API to create new cases for each review — made easy by the manuscript-api npm module.

The /pushContent endpoint is simple:

curl -X "POST" "https://youraccount.manuscript.com/api/pushContent" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
       "token": “yourSecretAPIToken”,
       "sTitle": "New Case Created With Push Content",
       "sText": "\\"Hello!\\""
}'

Note that instead of sending sText, you can send sHtml. This could make for nicer formatting of the content sent.

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.