We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 9130
    • 171 Posts
    Facebook recently changed the way custom tabs are created on Facebook fan pages. The former built-in solution Static FBML is now gone and if you need to add your own custom tab you can either use one of the available third party services or create you own solution.
    I will show how to create a Facebook fan page tab from scratch using modx with a fan gate feature showing different content to fans of your page.

    This tutorial assumes you already are an admin of a Facebook fan page, if not there is plenty of documentation on the web explaining how to create a Facebook fan page.

    So lets get to work:
    1. Got to Facebook developer application, http://www.facebook.com/developers and create new Facebook application, you might need to verify your account.

    2. In the applications settings copy the setting from the following image replacing example.com and the Tab URL with your own. Save the settings and copy the application secret for later use. 


    3. Go to the application profile page and click 'Add to My Page', select your fan page and add the application to your page. Now your fan page should have a new blank tab named 'Welcome'.

    4. Now that we are done setting everything up on Facebook go to the modx manager and create a new template - Facebook Page Template.
    Here is my simplified template code:
    <html>
    <head>
    <link rel="stylesheet" href="http://modx.com/assets/components/discuss/themes/modx/css/index.css" type="text/css" />
    <script type="text/javascript" src="http://modx.com/assets/components/discuss/themes/modx/js/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="http://modx.com/assets/components/discuss/themes/modx/js/jquery.scrollTo-min.js"></script>
    <script type="text/javascript" src="http://modx.com/assets/components/discuss/themes/modx/js/discuss.js"></script>
    <script type="text/javascript" src="http://modx.com/assets/components/discuss/themes/modx/js/sh/shCore.js"></script>
    <script type="text/javascript" src="http://modx.com/assets/components/discuss/themes/modx/js/sh/shAutoloader.js"></script>
    <script type="text/javascript" src="http://modx.com/assets/components/discuss/themes/modx/js/sh/shDiscuss.js"></script>
    <script type="text/javascript" src="http://modx.com/assets/components/discuss/themes/modx/js/dis.sticky.js"></script>
    <script type="text/javascript">// <![CDATA[
    DIS.url = "/";DIS.shJsUrl = "http://modx.com/assets/components/discuss/themes/modx/js/sh/";DIS.config.connector = "http://modx.com/assets/components/discuss/connector.php"
    // ]]></script>
    <script type="text/javascript" src="http://modx.com/assets/components/discuss/themes/modx/js/dis.post.modify.js"></script>
    <script type="text/javascript" src="http://modx.com/assets/components/discuss/themes/modx/js/dis.post.buttons.js"></script>
    </head>
    <body style="width: 520px; overflow: hidden;">
    [!fangate!]
    <script type="text/javascript">
            var DISModifyPost = $(function() {
                DIS.config.attachments_max_per_post = 5;
                DIS.DISModifyPost.init({
                    attachments: 1
                });
            });</script>
    </body>
    </html>

    Note the style of the body, Facebook tabs are only 520 pixels wide, any more then that and we will get unwanted scroll bars.

    5. Create a richtext TV named fangate and link it to the Facebook Page Template

    6. Create a snippet named fangate with the follwing content:
    <?php
    //your application secret goes here
    $app_secret = "1234567890";
    
    $output = "General error";
    $signed_request = $_REQUEST['signed_request'];
    
    //read signed request
    if(!$signed_request === true){
    	$output = "Error no page requested";
    } else {
    	$data = parse_signed_request($signed_request, $app_secret);
    	
    	if(!$data === true){
    		$output = "Error invalid signature";
    	} else {
    		$page = $data['page'];
    		if($page == null){
    			$output = "Error no page requested";
    		} else {
    			$fbpageid = $page['id']; //the requested page id
    			$fbadmin = $page['admin']; //user is page admin
    			$fbfan = $page['liked']; //user is page fan
    
    			if($fbfan == "1"){
    				$output = $modx->documentObject['content'];
    			} else {
    				$docid = (isset($docid))? $docid: $modx->documentIdentifier;
    				$document_tvs=$modx->getTemplateVarOutput(array('fangate'), $docid);
    				$output = $document_tvs['fangate'];
    			}
    		}	
    	}
    }
    
    return $output;
    
    function parse_signed_request($signed_request, $secret) {
      list($encoded_sig, $payload) = explode('.', $signed_request, 2); 
    
      // decode the data
      $sig = base64_url_decode($encoded_sig);
      $data = json_decode(base64_url_decode($payload), true);
    
      if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
        error_log('Unknown algorithm. Expected HMAC-SHA256');
        return null;
      }
    
      // check sig
      $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
      if ($sig !== $expected_sig) {
        error_log('Bad Signed JSON signature!');
        return null;
      }
    
      return $data;
    }
    
    function base64_url_decode($input) {
      return base64_decode(strtr($input, '-_', '+/'));
    }
    ?>

    Replace the $app_secret with your real application secret from step 2

    7. Create a new document with the same URL alias as you defined in the Facebook application's tab URL (fbpage in this example)
    - assign the Facebook Page Template to the document
    - in the content section enter the html to be seen only by the page fans
    - in the fangate tv enter the html to be seen by all other users

    And we are done, now go to your fan page and open the Welcome tab, you should see the fan restricted content. You can test the fangate function by logging out of Facebook and going to the Welcome tab, you should now see the unrestricted content.

    Hope you guys (and gals) find this helpful,
    Erez [ed. note: etal last edited this post 15 years, 1 month ago.]
      • 26931
      • 2,314 Posts
      thanks for sharing Erez!
        • 33337
        • 3,975 Posts
        Awesome!

        Thanks for sharing. laugh
          Zaigham R - MODX Professional | Skype | Email | Twitter

          Digging the interwebs for #MODX gems and bringing it to you. modx.link
          • 10903
          • 23 Posts
          Very interssting.

          However, I cannot get it to work. One way or the fangate snippet causes the iframe to only contain an empty head and body tag. Even the classes on the body tag are not published so it seems the template is never loaded. From the moment I disable the fanpage snippet in the template, the static content is displayed perfectly within Facebook.

          Any ides?

          Many tnx
          Gino
            • 10903
            • 23 Posts
            As i can see now, it is the function parse_signed_request that stops all processing of my page. Checking further ...
              • 10903
              • 23 Posts
              The problem is I’m using PHP v5.1 which not supports json_decode. Meanwhile I installed the PEAR Services_JSON as a workaround but cannot get it to work.

              Anyone with some advice here?

              Many tnx
              GIno
                • 9130
                • 171 Posts
                Have you tried installing the JSON PECL extension?
                This is the json package that was later integrated into php 5.2 so I assume that if you install this the code should just work.

                Or instead of installing packages just copy the code from simplejson-php into the snippet and use that to do the json decode.
                  • 10903
                  • 23 Posts
                  Thank you Etal.

                  The simplejson.php works for me.

                  Best regards
                  Gino
                    • 17412
                    • 270 Posts
                    Hi Etal,

                    I wonder if you can help, I’d like to set up a 3rd TV that allows a user who has already liked the page to revisit the page. See the problem I have is that I use the content TV to forward the user to Wall after they have liked with this:

                    <script type="text/javascript">
                    if (top != self) top.window.location = 'http://www.facebook.com/quinsrl?sk=wall';
                    </script>


                    I wonder if it’s possible to detect a user who has LIKED and who returns to the same page to output the content of a different TV "visitingagain" as below:

                    $fbfanvisited = $page['visited']; //user has liked page and clicks on it once more
                    
                    if($fbvisited == "1"){
                    			$docid = (isset($docid))? $docid: $modx->documentIdentifier;
                    			$document_tvs=$modx->getTemplateVarOutput(array('fangate'), $docid);
                    			$output = $document_tvs['visitingagain'];
                    			}


                    My app is hosted on my server and therefore I understand there may be issues with setting a cookie.

                    Any help, most gratefully received.

                    Thanks.
                      • 9130
                      • 171 Posts
                      There is no $page[’visited’] variable that you can get from facebook but you can achieve very a similar results using the session and some logic.

                      I would do something like this:
                      			if($fbfan == "1"){
                      				if($_SESSION['firstVisit'] == true){
                      				    $_SESSION['firstVisit'] = false;
                      				    $output = $modx->getChunk('redirectToWallScript');
                      				} else {
                      				    $output = $modx->documentObject['content'];
                      				}
                      			} else {
                      				$_SESSION['firstVisit'] = true;
                      				$docid = (isset($docid))? $docid: $modx->documentIdentifier;
                      				$document_tvs=$modx->getTemplateVarOutput(array('fangate'), $docid);
                      				$output = $document_tvs['fangate'];
                      			}
                      
                      


                      Most likely that if cookies don’t work then the session won’t not work either but I don’t understand why you think you have a problem there.