meddelare-server
Advanced tools
Comparing version 1.0.0 to 1.1.0
{ | ||
"name": "meddelare-server", | ||
"version": "1.0.0", | ||
"description": "Install social share counters on your website with your own hosted solution which only makes 1 API request and loads minimal or zero assets to display the counters.", | ||
"version": "1.1.0", | ||
"description": "Install custom social share counters on your website with your own hosted solution, which only makes a single API request and loads minimal or zero assets to display the counters.", | ||
"homepage": "http://meddelare.com/", | ||
@@ -15,5 +15,6 @@ "repository": { | ||
"dependencies": { | ||
"async": "~0.2.10", | ||
"bluebird": "^2.9.30", | ||
"cors": "~2.1.1", | ||
"express": "~3.4.8", | ||
"express": "^4.12.4", | ||
"morgan": "^1.5.3", | ||
"request": "~2.33.0" | ||
@@ -20,0 +21,0 @@ }, |
144
README.md
# [Meddelare](http://meddelare.com/) Social Buttons Server [meddelare-node-server](https://github.com/meddelare/meddelare-node-server) | ||
Install social share counters on your website with your own hosted solution which only makes 1 API request and loads minimal or zero assets to display the counters. | ||
Install **custom social share counters** on your website with your **own hosted solution**, which only makes **a single API request** and loads **minimal or zero assets** to display the counters. | ||
This is an open source and self-hosted alternative to services such as AddThis and ShareThis. | ||
Check out [meddelare.com](http://meddelare.com/)! | ||
Because you run the middle man server your self, you are also defending your users privacy against the social networks. (Users only opt into the tracking once they decide to share and not just because they visited your page) | ||
This is an open source and self-hosted alternative to sharing services such as AddThis and ShareThis. Because you run the proxy server yourself, you are also defending your users' privacy against the social networks' tracking. Users only opt in to their tracking once they decide to click a share button -- never implicitly just because they visited your page. | ||
* [Example API Call](https://meddelare-node-server.herokuapp.com/?networks=facebook,twitter,googleplus&url=http://meddelare.com) | ||
* [Example API Call with Buttons](https://meddelare.github.io/meddelare-examples/examples/button.html) | ||
* [Example API Call with Text (fast)](https://meddelare.github.io/meddelare-examples/examples/text.html) | ||
[![A screenshot of the button example](https://meddelare.github.io/examples/button/screenshot.png)](https://meddelare.github.io/) | ||
View examples on [meddelare.github.io/meddelare-examples](https://meddelare.github.io/meddelare-examples). | ||
## Features | ||
* Heroku enabled, create an app and deploy instantly | ||
* Has cache control variable(default 4 mins) so you can throw CloudFront in front with ease which result in faster API calls and less chance of getting rate limited | ||
## Getting started | ||
- Get counts from multiple social networks in one API call, delivered as [JSON](https://en.wikipedia.org/wiki/JSON) or [JSONP](https://en.wikipedia.org/wiki/JSONP). | ||
- The server calls social networks in parallel, making it (approximately) as fast to get the count from one as several at once. | ||
- No third party requirements -- you can host both the social buttons server and any resources yourself. | ||
- Proxies calls from your users to the social networks, blocking their user tracking until the user decides to click a share button. | ||
- Heroku enabled -- create an app and deploy instantly. | ||
- Sends cache control HTTP headers so you can throw a [content delivery network](https://en.wikipedia.org/wiki/Content_delivery_network) (CDN) service, such as CloudFront, in front with ease. This should result in faster API calls and less chance of getting rate limited. | ||
1. Clone(or fork) the repository | ||
2. Install dependencies `npm install` | ||
3. Run the server `node social-buttons-server.js` | ||
4. Access your stats at `http://localhost:5000/?networks=facebook,twitter,googleplus&url=http://meddelare.com` | ||
5. __Optionally push to a heroku app to automatically deploy__ | ||
## Options | ||
Options are passed through query parameters in the url | ||
## Getting started | ||
### Networks | ||
```bash | ||
# Clone the repository | ||
git clone https://github.com/meddelare/meddelare-node-server.git | ||
Currently only Twitter, Facebook and Google Plus are supported | ||
cd meddelare-node-server | ||
You use the `networks` query parameter to specify which ones you want to use as a comma-separated list e.g. | ||
# Install dependencies | ||
npm install | ||
`networks=facebook,twitter,googleplus` or `networks=facebook` | ||
# Run the server | ||
node social-buttons-server.js | ||
``` | ||
### Url | ||
- Test by accessing your local server on [http://localhost:5000/?networks=facebook,twitter,googleplus&url=http://meddelare.com](http://localhost:5000/?networks=facebook,twitter,googleplus&url=http://meddelare.com) | ||
- You can optionally push to a Heroku app to automatically deploy. | ||
You use the `url` parameter to specify the address which you want to count the total number of shares for e.g. `url=http://1984day.com` | ||
If you don't specify a `url` then the server will try to get the referring urls total share count. So if you make the API call on your homepage without the `url` parameter, the API server will return the numbe rof shares for your homepage url. | ||
## CloudFront | ||
## Response | ||
You don't want to be hitting the social networks API's constantly so it would be wise to throw up a cache in front such as CloudFront. | ||
See this [example API call](https://meddelare-node-server.herokuapp.com/?networks=facebook,twitter,googleplus&url=http://meddelare.com). The response is delivered as JSON, or JSONP if you specify a callback. | ||
In CloudFront just make sure you to inherit cache control directives from the server and enable query string forwarding. | ||
```json | ||
{ | ||
"facebook": 5281, | ||
"googleplus": 42, | ||
"twitter": 8719 | ||
} | ||
``` | ||
Eithr use your CloudFront url to access the API server or cname it with a custom domain of your choice. | ||
## Cross domain | ||
The server as it is has CORS enabled which means any website can call the API SERVER. You can easily white list if this becomes a problem. | ||
## HTML Widgets | ||
**We would love to start collecting widgets that people design and want to share, please submit them in a pull request to [meddelare-examples](https://github.com/meddelare/meddelare-examples) and we will create a new section to list them** | ||
View examples on [meddelare.github.io/meddelare-examples](https://meddelare.github.io/meddelare-examples). | ||
You can do anything you want to display your share totals when using the API. There are the examples linked at the top of the README and some short code below. Notice that we are using a CloudFront distribution in the examples. | ||
**We would love to feature your widget design!** | ||
Please submit your design in a pull request to [meddelare-examples](https://github.com/meddelare/meddelare-examples) and we will add it to our list. | ||
You can do anything you want to display your share counts when using the API. Below is a very simple example showing the count per network -- see this [example API call with text](https://meddelare.github.io/meddelare-examples/examples/text/). Note that we are using a CloudFront distribution domain in the examples. | ||
```html | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
</head> | ||
<body> | ||
<h3>Twitter</h3> | ||
<body> | ||
<h3>Twitter</h3> | ||
<span id="twitter"></span> | ||
@@ -75,13 +81,13 @@ <h3>Facebook</h3> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> | ||
<script type="text/javascript"> | ||
$.ajax('https://d12cncu17l9pr5.cloudfront.net/?networks=facebook,twitter,googleplus&url=http://meddelare.com', { | ||
success: function (res, err) { | ||
$.each(res, function(network, value){ | ||
$('#'+network).text(value); | ||
}) | ||
} | ||
}) | ||
</script> | ||
</body> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> | ||
<script> | ||
$.ajax("https://d12cncu17l9pr5.cloudfront.net/?networks=facebook,twitter,googleplus&url=http://meddelare.com", { | ||
success: function (res, err) { | ||
$.each(res, function (network, value) { | ||
$("#" + network).text(value); | ||
}); | ||
} | ||
}); | ||
</script> | ||
</body> | ||
</html> | ||
@@ -92,2 +98,46 @@ ``` | ||
## Options | ||
Options are passed using query parameters in the url. | ||
**Networks** | ||
Currently Twitter, Facebook and Google Plus are supported. | ||
You use the `networks` query parameter to specify which ones you want to use as a comma-separated list (no spaces), for example `networks=facebook,twitter,googleplus` or `networks=facebook`. | ||
**Url (optional)** | ||
You use the `url` parameter to specify the address which you want to retrieve the number of shares for, for example `url=http://meddelare.com`. | ||
If you don't specify a `url` then the server will try to get the referring url's (HTTP `Referer` header) share count. This makes it easy to dynamically get the counts for the page currently open in the browser. | ||
**Callback (optional)** | ||
If you specify the `callback` parameter, the results will be delivered as JSONP instead of plain JSON. | ||
## Configuration | ||
Configure the node.js server instance at launch time. Where you set the environment variable depends on your system, but examples below are using the command line. | ||
**HTTP cache time** | ||
The environment variable `CACHE_TIME` can be used to set the time, in seconds, that the browser (or CDN) should cache results. Cached results vary on the request query string. To set the HTTP cache to ten minutes, use `CACHE_TIME=600 node social-buttons-server.js`. | ||
**Cross-domain requests** | ||
The server has [cross-origin resource sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) (CORS) enabled for whitelisted domains, which need to be configured in the file `social-buttons-server.js`. | ||
## Content delivery networks | ||
You don't want to be hitting the social networks APIs constantly so it would be wise to throw up a cache, such as CloudFront, in front. | ||
In CloudFront, just make sure you to inherit cache control directives from the server and enable query string forwarding. Either use your CloudFront distribution domain to access the API server or `CNAME` it with a custom domain of your choice. | ||
## Thanks | ||
@@ -94,0 +144,0 @@ |
@@ -1,14 +0,20 @@ | ||
var async = require('async'); | ||
var cors = require('cors'); | ||
var express = require('express'); | ||
var request = require('request'); | ||
// How many minutes should we cache the results for a given request | ||
var CACHE_TIME = process.env.CACHE_TIME || 4 * 60; | ||
var PORT = process.env.PORT || 5000; | ||
var socialButtonsServer = require('./lib/social-buttons-server-middleware.js'); | ||
var app = express(); | ||
app.use(express.logger()); | ||
var morgan = require("morgan"); | ||
var expressLogger = morgan("combined", { | ||
skip: function(req, res) { | ||
return res.statusCode < 400; | ||
} | ||
}); | ||
app.use(expressLogger); | ||
var whitelist = [ | ||
@@ -38,9 +44,2 @@ 'http://localhost:4000', | ||
// Setup caching headers (works well with cloudfront) | ||
app.use(function (req, res, next) { | ||
res.set('Cache-Control', 'max-age=' + CACHE_TIME); | ||
next(); | ||
}); | ||
app.use(cors(corsOptions)); | ||
@@ -50,105 +49,6 @@ | ||
var networkCallbacks = { | ||
twitter: function (url, callback) { | ||
// Twitter is nice and easy | ||
var apiUrl = 'http://urls.api.twitter.com/1/urls/count.json?url=' + url; | ||
app.use("/", socialButtonsServer()); | ||
request.get({ url: apiUrl, json: true }, function (err, res, body) { | ||
if (err) { | ||
return callback(null, 0); | ||
} | ||
callback(null, body.count); | ||
}); | ||
}, | ||
facebook: function (url, callback) { | ||
// This query string gets the total number of likes, shares and comments to | ||
// create the final count | ||
var apiUrl = 'https://graph.facebook.com/fql?q=SELECT%20url,' + | ||
'%20normalized_url,%20share_count,%20like_count,%20comment_count,' + | ||
'%20total_count,commentsbox_count,%20comments_fbid,' + | ||
'%20click_count%20FROM%20link_stat%20WHERE%20url="' + url + '"'; | ||
request.get({ url: apiUrl, json: true }, function (err, res, body) { | ||
if (err) { | ||
return callback(null, 0); | ||
} | ||
var count = 0; | ||
if (body.data.length > 0) { | ||
count = body.data[0].total_count; | ||
} | ||
callback(null, count); | ||
}); | ||
}, | ||
googleplus: function (url, callback) { | ||
// This is a hacky method found on the internet because google doesn't have | ||
// an API for google plus counts | ||
var apiUrl = 'https://plusone.google.com/_/+1/fastbutton?url=' + url; | ||
request.get(apiUrl, function (err, res, body) { | ||
if (err) { | ||
return callback(null, 0); | ||
} | ||
var result = /__SSR \= \{c\: (.*?)\.0/g.exec(body); | ||
var count = 0; | ||
if (result) { | ||
count = result[1] * 1; | ||
} | ||
callback(null, count); | ||
}); | ||
} | ||
}; | ||
app.get('/', function (req, res) { | ||
var url; | ||
// Check to see if any networks were specified in the query | ||
if (!req.param('networks')) { | ||
return res.send({ | ||
error: 'You have to specify which networks you want stats for ' + | ||
'(networks=facebook,twitter,googleplus)' | ||
}); | ||
} | ||
// Check to see if a url was specified in the query else attempt to use the | ||
// referer url | ||
if (req.param('url')) { | ||
url = req.param('url'); | ||
} else { | ||
url = req.header('Referer'); | ||
if (!url) { | ||
return res.send({ | ||
error: 'You asked for the referring urls stats but there is no ' + | ||
'referring url, specify one manually (&url=http://1984day.com)' | ||
}); | ||
} | ||
} | ||
// Create an object of callbacks for each of the requested networks It is | ||
// then passed to the async library to executed in parallel All results will | ||
// be sent to the browser on completion. | ||
var networksToRequest = {}; | ||
req.param('networks').split(',').forEach(function (network) { | ||
if (typeof networkCallbacks[network] !== 'undefined') { | ||
networksToRequest[network] = function (callback) { | ||
networkCallbacks[network](url, callback); | ||
}; | ||
} | ||
}); | ||
async.parallel(networksToRequest, function (err, results) { | ||
res.jsonp(results); | ||
}); | ||
}); | ||
app.listen(PORT, function () { | ||
console.log('Listening on ' + PORT); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14916
7
167
152
5
1
+ Addedbluebird@^2.9.30
+ Addedmorgan@^1.5.3
+ Addedaccepts@1.3.8(transitive)
+ Addedarray-flatten@1.1.1(transitive)
+ Addedbasic-auth@2.0.1(transitive)
+ Addedbluebird@2.11.0(transitive)
+ Addedbody-parser@1.20.3(transitive)
+ Addedbytes@3.1.2(transitive)
+ Addedcall-bind@1.0.7(transitive)
+ Addedcontent-disposition@0.5.4(transitive)
+ Addedcontent-type@1.0.5(transitive)
+ Addedcookie@0.7.1(transitive)
+ Addedcookie-signature@1.0.6(transitive)
+ Addeddebug@2.6.9(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addeddepd@2.0.0(transitive)
+ Addeddestroy@1.2.0(transitive)
+ Addedee-first@1.1.1(transitive)
+ Addedencodeurl@1.0.22.0.0(transitive)
+ Addedes-define-property@1.0.0(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedescape-html@1.0.3(transitive)
+ Addedetag@1.8.1(transitive)
+ Addedexpress@4.21.1(transitive)
+ Addedfinalhandler@1.3.1(transitive)
+ Addedforwarded@0.2.0(transitive)
+ Addedfresh@0.5.2(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedget-intrinsic@1.2.4(transitive)
+ Addedgopd@1.0.1(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.0.3(transitive)
+ Addedhas-symbols@1.0.3(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedhttp-errors@2.0.0(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedipaddr.js@1.9.1(transitive)
+ Addedmedia-typer@0.3.0(transitive)
+ Addedmerge-descriptors@1.0.3(transitive)
+ Addedmethods@1.1.2(transitive)
+ Addedmime@1.6.0(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedmorgan@1.10.0(transitive)
+ Addedms@2.0.02.1.3(transitive)
+ Addednegotiator@0.6.3(transitive)
+ Addedobject-inspect@1.13.3(transitive)
+ Addedon-finished@2.3.02.4.1(transitive)
+ Addedon-headers@1.0.2(transitive)
+ Addedparseurl@1.3.3(transitive)
+ Addedpath-to-regexp@0.1.10(transitive)
+ Addedproxy-addr@2.0.7(transitive)
+ Addedqs@6.13.0(transitive)
+ Addedrange-parser@1.2.1(transitive)
+ Addedraw-body@2.5.2(transitive)
+ Addedsafe-buffer@5.1.25.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsend@0.19.0(transitive)
+ Addedserve-static@1.16.2(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedsetprototypeof@1.2.0(transitive)
+ Addedside-channel@1.0.6(transitive)
+ Addedstatuses@2.0.1(transitive)
+ Addedtoidentifier@1.0.1(transitive)
+ Addedtype-is@1.6.18(transitive)
+ Addedunpipe@1.0.0(transitive)
+ Addedutils-merge@1.0.1(transitive)
+ Addedvary@1.1.2(transitive)
- Removedasync@~0.2.10
- Removedasync@0.2.10(transitive)
- Removedbatch@0.5.0(transitive)
- Removedbuffer-crc32@0.2.1(transitive)
- Removedbytes@0.2.1(transitive)
- Removedcommander@1.3.2(transitive)
- Removedconnect@2.12.0(transitive)
- Removedcookie@0.1.0(transitive)
- Removedcookie-signature@1.0.1(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removeddebug@0.8.1(transitive)
- Removedexpress@3.4.8(transitive)
- Removedfresh@0.2.0(transitive)
- Removedisarray@0.0.1(transitive)
- Removedkeypress@0.1.0(transitive)
- Removedmerge-descriptors@0.0.1(transitive)
- Removedmethods@0.1.0(transitive)
- Removedmkdirp@0.3.5(transitive)
- Removedmultiparty@2.2.0(transitive)
- Removednegotiator@0.3.0(transitive)
- Removedpause@0.0.1(transitive)
- Removedrange-parser@0.0.4(transitive)
- Removedraw-body@1.1.2(transitive)
- Removedreadable-stream@1.1.14(transitive)
- Removedsend@0.1.4(transitive)
- Removedstream-counter@0.2.0(transitive)
- Removedstring_decoder@0.10.31(transitive)
- Removeduid2@0.0.3(transitive)
Updatedexpress@^4.12.4