54

I am trying to create a Facebook iFrame app. The app should first show an image and if the user likes the page, he will get access to some content.

I use RoR, therefore I can't use the Facebook PhP SDK.

Here is my iFrame HTML when the user has not liked the page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<link rel="stylesheet" type="text/css" href="style.css" />
<style type="text/css">
body {
width:520px;
margin:0; padding:0; border:0;
font-family: verdana;
background:url(repeat.png) repeat;
margin-bottom:10px;
}
p, h1 {width:450px; margin-left:50px; color:#FFF;}
p {font-size:11px;}
</style>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1" />
</head>
<body>
<div id="container">
<img src="welcome.png" alt="Frontimg">
</div>

And, if the user has liked the page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<link rel="stylesheet" type="text/css" href="style.css" />
<style type="text/css">
body {
width:520px;
margin:0; padding:0; border:0;
font-family: verdana;
background:url(repeat.png) repeat;
margin-bottom:10px;
}
p, h1 {width:450px; margin-left:50px; color:#FFF;}
p {font-size:11px;}
</style>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1" />
</head>
<body>
<div id="container">
<img src="member.png" alt="Frontimg">
<p>You liked this page</p>

Christian Fazzini
  • 19,613
  • 21
  • 110
  • 215
Rails beginner
  • 14,321
  • 35
  • 137
  • 257
  • Yes i know th FB JS SDK - But i dont know how to use it – Rails beginner Jun 09 '11 at 21:05
  • 2 other questions before I give it a shot : Is it really sensitive information ? Because one approach involve showing one div with js if the user like the page and showing another div if the user don't like the page (both divs being hidden in the page at start) so somebody could unhide them with firebug or something else and see your content. Another approach involves fetching the content of the two divs by ajax which is more "secure". Also what JS library do you use I'm a jquery'ist so can I use jquery ? – dwarfy Jun 10 '11 at 05:57

6 Answers6

80

UPDATE 21/11/2012 @ALL : I have updated the example so that it works better and takes into accounts remarks from Chris Jacob and FB Best practices, have a look of working example here


Hi So as promised here is my answer using only javascript :

The content of the BODY of the page :

<div id="fb-root"></div>
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script>
  FB.init({
    appId  : 'YOUR APP ID',
    status : true, 
    cookie : true, 
    xfbml  : true  
  });
</script>

<div id="container_notlike">
YOU DONT LIKE
</div>

<div id="container_like">
YOU LIKE
</div>

The CSS :

body {
width:520px;
margin:0; padding:0; border:0;
font-family: verdana;
background:url(repeat.png) repeat;
margin-bottom:10px;
}
p, h1 {width:450px; margin-left:50px; color:#FFF;}
p {font-size:11px;}

#container_notlike, #container_like {
    display:none
}

And finally the javascript :

$(document).ready(function(){

    FB.login(function(response) {
      if (response.session) {

          var user_id = response.session.uid;
          var page_id = "40796308305"; //coca cola
          var fql_query = "SELECT uid FROM page_fan WHERE page_id = "+page_id+"and uid="+user_id;
          var the_query = FB.Data.query(fql_query);

          the_query.wait(function(rows) {

              if (rows.length == 1 && rows[0].uid == user_id) {
                  $("#container_like").show();

                  //here you could also do some ajax and get the content for a "liker" instead of simply showing a hidden div in the page.

              } else {
                  $("#container_notlike").show();
                  //and here you could get the content for a non liker in ajax...
              }
          });


      } else {
        // user is not logged in
      }
    });

});

So what what does it do ?

First it logins to FB (if you already have the USER ID, and you are sure your user is already logged in facebook, you can bypass the login stuff and replace response.session.uid with YOUR_USER_ID (from your rails app for example)

After that it makes a FQL query on the page_fan table, and the meaning is that if the user is a fan of the page, it returns the user id and otherwise it returns an empty array, after that and depending on the results its show a div or the other.

Also there is a working demo here : http://jsfiddle.net/dwarfy/X4bn6/

It's using the coca-cola page as an example, try it go and like/unlike the coca cola page and run it again ...

Finally some related docs :

FQL page_fan table

FBJS FB.Data.query

Don't hesitate if you have any question ..

Cheers

UPDATE 2

As stated by somebody, jQuery is required for the javascript version to work BUT you could easily remove it (it's only used for the document.ready and show/hide).

For the document.ready, you could wrap your code in a function and use body onload="your_function" or something more complicated like here : Javascript - How to detect if document has loaded (IE 7/Firefox 3) so that we replace document ready.

And for the show and hide stuff you could use something like : document.getElementById("container_like").style.display = "none" or "block" and for more reliable cross browser techniques see here : http://www.webmasterworld.com/forum91/441.htm

But jQuery is so easy :)

UPDATE

Relatively to the comment I posted here below here is some ruby code to decode the "signed_request" that facebook POST to your CANVAS URL when it fetches it for display inside facebook.

In your action controller :

decoded_request = Canvas.parse_signed_request(params[:signed_request])

And then its a matter of checking the decoded request and display one page or another .. (Not sure about this one, I'm not comfortable with ruby)

decoded_request['page']['liked']

And here is the related Canvas Class (from fbgraph ruby library) :

 class Canvas

    class << self
      def parse_signed_request(secret_id,request)
        encoded_sig, payload = request.split('.', 2)
        sig = ""
        urldecode64(encoded_sig).each_byte { |b|
          sig << "%02x" % b
        }
        data = JSON.parse(urldecode64(payload))
          if data['algorithm'].to_s.upcase != 'HMAC-SHA256'
          raise "Bad signature algorithm: %s" % data['algorithm']
        end
        expected_sig = OpenSSL::HMAC.hexdigest('sha256', secret_id, payload)
        if expected_sig != sig
          raise "Bad signature"
        end
        data
      end

      private

      def urldecode64(str)
        encoded_str = str.gsub('-','+').gsub('_','/')
        encoded_str += '=' while !(encoded_str.size % 4).zero?
        Base64.decode64(encoded_str)
      end
    end  

 end
Community
  • 1
  • 1
dwarfy
  • 3,076
  • 18
  • 22
  • 1
    Actually while it's still interesting to see how to do this in javascript, as you are in a iframe app, you SHOULD consider decoding the [signed_request](http://developers.facebook.com/docs/authentication/signed_request/) that facebook sends to your page as a POST parameter when it fetches it to display in the iframe. – dwarfy Jun 11 '11 at 07:01
  • See my UPDATE ... It should do the trick (probably a better solution than the javascript) – dwarfy Jun 11 '11 at 07:27
  • On the JS side when I tried your demo it pops up with the request for permission box. Is there a way around that? I'm trying to do this on a website to see if they like our fan page and it not show some different content but if there is that pop up asking for permission then they will probably just leave the site. – kel Jun 16 '11 at 01:22
  • @kel : I'm sorry to say that but there is no way to bypass the permissions stuff. I mean the users have to accept it ONCE. If your user are already logged on facebook through your site then you can use their access_token without doing the JS login, otherwise NOT. Are user already logged on facebook through your site ? – dwarfy Jun 16 '11 at 07:41
  • @dwarfy No the don't login to my site. How is it that the Facebook like box know if you like a page or not? Is it just because it's facebook? – kel Jun 17 '11 at 03:11
  • @kel I'm not sure that facebook like box can know if you like the page without checking your cookies or something to find your facebook ID and then checking if you like the page ... or by asking to login to facebook if it can't find a cookie ... – dwarfy Jun 17 '11 at 07:47
  • @kel I tried it and that's what I tought, See an example here : http://jsfiddle.net/dwarfy/fkq6A/show/ If you open another tab and login to facebook, then you go back to the example you will be able to like directly, now if you go back to facebook and logout, then you refresh the example page and you try to like, it will ask you to login to facebook first ... (and it won't know if you already like or not ..) – dwarfy Jun 17 '11 at 07:49
  • @dwarfy, I completely understand that you have to be logged into Facebook for to know if you like the page. That is what I'm trying to accomplish is if they are logged in to see if they like our page. If they don't like it or not logged in then to show something. – kel Jun 21 '11 at 20:36
  • I didn't see this mentioned in your answer, but jQuery is needed for this to work. Otherwise, worked fine for me :) – topher-j Aug 05 '11 at 15:16
  • @topher-j : you are right but jQuery is only needed for the document.ready stuff which could be easily removed with body onload or something from standard js :) – dwarfy Aug 08 '11 at 06:35
  • @topher-j : I put a notice about that in the answer, thanks for the comments :) – dwarfy Aug 08 '11 at 06:49
  • Best Practices (from http://developers.facebook.com/docs/reference/javascript/FB.login/) FB.login opens a popup window, and therefore you should only call FB.login when bound to a user driven click. Most browsers block popups, unless they were initiated from a user event, such as a click on a button or a link. – Chris Jacob Dec 15 '11 at 13:45
  • I want to use this code to check user linke page or not. I dont have " APP ID". How should I do? – Jeyhun Rahimov Nov 21 '12 at 08:36
  • @Mores You should go to developers.facebook.com and create an application for your purposes. You would then get and APP ID – dwarfy Nov 21 '12 at 09:42
  • I created app and get APP_ID, used it in code, but there is not result. Or can you help to know user likes page or not (yes or not) without application, only in html page with javascript? – Jeyhun Rahimov Nov 21 '12 at 09:56
  • @Mores : please have a look here http://jsfiddle.net/X4bn6/1042/ I just updated my example so that it works again and respects facebook best practices .. – dwarfy Nov 21 '12 at 13:53
  • @dwarfy, thank you very much for this. I saw in some sites, they determine me like their page or not without fb app. Maybe they hide application. Because user dont like any application firstly. I just want to do this without application. Is it possible? – Jeyhun Rahimov Nov 22 '12 at 06:47
  • @Mores : I think the only way to do it without application is to use the facebook like button https://developers.facebook.com/docs/reference/plugins/like/ or another of the facebook social widgets https://developers.facebook.com/docs/plugins/ – dwarfy Nov 23 '12 at 09:20
  • @Dwarfy, it will not help me, to my mind. Shortly, I want to do this in my site: Assume that, I know user's facebook ID. I Have some pages, in my site I want to check which of my pages does current user like. If he liked my pages I will give some advantage him – Jeyhun Rahimov Nov 23 '12 at 13:13
  • FB.Data.query is good. no need to request user's like permission – Cullen SUN Oct 03 '13 at 09:40
  • @dwarfy Thank You man for the answer. But this uses FQL which is gone now. Any way to do this via the Graph API ? – Patrick Mar 07 '15 at 07:14
19

You need to write a little PHP code. When user first click tab you can check is he like the page or not. Below is the sample code

include_once("facebook.php");

    // Create our Application instance.
    $facebook = new Facebook(array(
      'appId'  => FACEBOOK_APP_ID,
      'secret' => FACEBOOK_SECRET,
      'cookie' => true,
    ));

$signed_request = $facebook->getSignedRequest();

// Return you the Page like status
$like_status = $signed_request["page"]["liked"];

if($like_status)
{
    echo 'User Liked the page';
    // Place some content you wanna show to user

}else{
    echo 'User do not liked the page';
    // Place some content that encourage user to like the page
}
Inam Abbas
  • 1,480
  • 14
  • 28
  • I am not expert of ROR though you can found something similar in ROR API for facebook as if they are providing it for PHP they definitely for ROR too. – Inam Abbas Jun 08 '11 at 21:45
  • 1
    Do you see the "php" tag somewhere ? The guy want something in ruby or javascript .. – dwarfy Jun 11 '11 at 07:25
  • 1
    @mani, I received a lot of -1 from sick men like me and it made me read the questions and tag more carefully before answering ... sorry if you felt hurt tough – dwarfy Jun 14 '11 at 08:14
  • 10
    Even though it was slightly off topic from the OP's question I am glad the information was here as it was helpful for my situation. – Kenneth Jun 16 '11 at 05:25
  • Ok I tried to remove my -1 realizing that I maybe had been to severe .. but it doesn't allow me to change it unless the writer changes the content a little bit .. – dwarfy Jun 16 '11 at 07:47
  • 1
    @mani I, for one, am glad you posted this solution! While it may not have answered rails beginner's exact question it's the perfect solution for my problem having landed here from a Google SERP. – Terri Ann Jan 13 '12 at 19:11
5

Here's a working example, which is a fork of this answer:

$(document).ready(function(){
    FB.login(function(response) {
        if (response.status == 'connected') {
            var user_id = response.authResponse.userID;
            var page_id = "40796308305"; // coca cola page https://www.facebook.com/cocacola
            var fql_query = "SELECT uid FROM page_fan WHERE page_id="+page_id+" and uid="+user_id;

            FB.api({
                method: 'fql.query',
                query: fql_query
            },
            function(response){
                if (response[0]) {
                    $("#container_like").show();
                } else {
                    $("#container_notlike").show();
                }
            }
            );    
        } else {
        // user is not logged in
        }
    });
});

I used the FB.api method (JavaScript SDK), instead of FB.Data.query, which is deprecated. Or you can use the Graph API like with this example:

$(document).ready(function() {
    FB.login(function(response) {
        if (response.status == 'connected') {
            var user_id = response.authResponse.userID;
            var page_id = "40796308305"; // coca cola page https://www.facebook.com/cocacola
            var fql_query = "SELECT uid FROM page_fan WHERE page_id=" + page_id + " and uid=" + user_id;

            FB.api('/me/likes/'+page_id, function(response) {
                if (response.data[0]) {
                    $("#container_like").show();
                } else {
                    $("#container_notlike").show();
                }
            });
        } else {
            // user is not logged in
        }
    });
});​
Community
  • 1
  • 1
2

There are some changes required to JavaScript code to handle rendering based on user liking or not liking the page mandated by Facebook moving to Auth2.0 authorization.

Change is fairly simple:-

sessions has to be replaced by authResponse and uid by userID

Moreover given the requirement of the code and some issues faced by people(including me) in general with FB.login, use of FB.getLoginStatus is a better alternative. It saves query to FB in case user is logged in and has authenticated your app.

Refer to Response and Sessions Object section for info on how this might save query to FB server. http://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/

Issues with FB.login and its fixes using FB.getLoginStatus. http://forum.developers.facebook.net/viewtopic.php?id=70634

Here is the code posted above with changes which worked for me.

$(document).ready(function(){
    FB.getLoginStatus(function(response) {
        if (response.status == 'connected') {
            var user_id = response.authResponse.userID;
            var page_id = "40796308305"; //coca cola
            var fql_query = "SELECT uid FROM page_fan WHERE page_id =" + page_id + " and uid=" + user_id;
            var the_query = FB.Data.query(fql_query);

            the_query.wait(function(rows) {

                if (rows.length == 1 && rows[0].uid == user_id) {
                    $("#container_like").show();

                    //here you could also do some ajax and get the content for a "liker" instead of simply showing a hidden div in the page.

                } else {
                    $("#container_notlike").show();
                    //and here you could get the content for a non liker in ajax...
                }
            });
        } else {
            // user is not logged in
        }
    });

});
karora
  • 238
  • 1
  • 8
1

With Javascript SDK, you can change the code as below, this should be added after FB.init call.

     // Additional initialization code such as adding Event Listeners goes here
FB.getLoginStatus(function(response) {
      if (response.status === 'connected') {
        // the user is logged in and has authenticated your
        // app, and response.authResponse supplies
        // the user's ID, a valid access token, a signed
        // request, and the time the access token 
        // and signed request each expire
        var uid = response.authResponse.userID;
        var accessToken = response.authResponse.accessToken;
        alert('we are fine');
      } else if (response.status === 'not_authorized') {
        // the user is logged in to Facebook, 
        // but has not authenticated your app
        alert('please like us');
         $("#container_notlike").show();
      } else {
        // the user isn't logged in to Facebook.
        alert('please login');
      }
     });

FB.Event.subscribe('edge.create',
function(response) {
    alert('You liked the URL: ' + response);
      $("#container_like").show();
}
Sofia Khwaja
  • 1,909
  • 3
  • 17
  • 20
0

There is an article here that describes your problem

http://www.hyperarts.com/blog/facebook-fan-pages-content-for-fans-only-static-fbml/

    <fb:visible-to-connection>
       Fans will see this content.
       <fb:else>
           Non-fans will see this content.
       </fb:else>
    </fb:visible-to-connection>
bkaid
  • 51,465
  • 22
  • 112
  • 128
Modatheus
  • 17
  • 1
  • Ah, then you need to do it through iFrame or Fan Gate when you created you site. You can read about it http://www.marismith.com/iframes-facebook-app-fan-gate-wildfire/ here, just look down on the site. – Modatheus Jun 06 '11 at 10:30