HTML - How to efficiently do multiple Facebook Like buttons on one page
Asked Answered
M

6

2

I have a page where I need to have about 30 Facebook Like buttons. They all Like the same url. Basically just duplicate HTML code everywhere.

Anyways, when you load the page, every single Facebook Like Button div makes calls back and forth to Facebook. You can see it in the dev tools going back and forth. Slows down the page load a lot.

Is there a more efficient solution to this problem?

UPDATE

Let me ask an alternate question: Is there any way to dynamically connect each Facebook div like button to Facebook servers on demand? So basically, when the page loads, none of the Facebook div's make the connection to Facebook and a script is able to go through each button and (on demand) run the script that connects it. Is this possible? Right now, it appears that the way it works is that my page downloads the all.js from Facebook. This script finds all facebook div's on the page and connects them to Facebook and makes them into Like buttons. If there was a way to run this script selectively on any div you wanted to, that would help me get closer to a solution...

Mccaleb answered 3/2, 2012 at 22:15 Comment(3)
If it's the same URL, what's wrong with just having one button?Blah
It's part of the design of the page. I'm just the developer, not the designer.Mccaleb
I was just curious; from an outside point of view, it seems silly to replicate the same piece of information 30 times, but of course it's out of your control :-)Blah
M
0

After much testing, this was my final solution:

Loading the Facebook all.js SDK automatically parses all Facebook Like buttons on the page. There is unfortunately no option to load the SDK without parsing existing Facebook Like buttons.

Two solutions:

  1. Load the SDK and not have any Facebook Like buttons on your page. Then, whenever there is a Like button that is visible on the screen, load in the Like button html/fbxml and then parse the markup using the SDK. I did not test this.

  2. Don't load the SDK at all. Simply use AJAX to dynamically add a Facebook iframe in wherever you want to load one up. I went with this solution.

Mccaleb answered 6/2, 2012 at 17:12 Comment(0)
W
4

If there was a way to run this script selectively on any div you wanted to, that would help me get closer to a solution...

yes, you can run FB.XFBML.parse(); on a particular DOM object. So dynamically add the like button code to the div, then call FB.XFBML.parse(); on it. See: http://developers.facebook.com/docs/reference/javascript/FB.XFBML.parse/

FB.XFBML.parse(document.getElementById('foo'));

Wilie answered 3/2, 2012 at 23:54 Comment(2)
Yeah I did see this. Trying to avoid using the XFBML markup and use the HTML5 implementation instead. Is there a similar parsing method for non-XFBML?Mccaleb
I think that the same parse method will even go out and find new instances of the HTML5 versions too.Wilie
R
3

I know this is an old topic but this may come in handy for others with the same problem.

If you have tons of facebook widgets for example one per result on a search results page and you want them all to render yet don't want to hit your user with tons of connections at the same time you can use this to throttle the rendering.

Code:

var fbThrottle = (function () {
    var settings = {
        // how many widgets can be rendering at any one time
        simultaneousRenders: 3,
        // how often to add a new widget to the queue, if the queue is not full
        renderInterval: 100,
        // max amount of time we will wait until marking a widget as rendered
        // this is in place so as not to block the queue if a widget takes too long
        maxRenderWaitFailsafe: 5000,
        // how long to wait before calling the callback function (if supplied)
        // after a widget finishes rendering. can be used to say set the area visible after render if you had it hidden to prevent fout.
        callbackDelay: 250,
    };

    var fbWidgets = [];
    var activeRenders = 0;

    setInterval(function () {
        if (fbWidgets.length == 0)
            return;

        if (!window.FB)
            return;

        if (activeRenders < settings.simultaneousRenders) {
            var obj = fbWidgets.shift();

            if (typeof obj !== 'undefined') {
                activeRenders++;

                (function () {
                    var currentRenderDone = false;

                    setTimeout(function () {
                        if (!currentRenderDone) {
                            activeRenders--;
                            currentRenderDone = true;
                        }
                    }, settings.maxRenderWaitFailsafe);

                    window.FB.XFBML.parse(obj.widget, function () {
                        if (!currentRenderDone) {
                            activeRenders--;
                            currentRenderDone = true;
                        }

                        if (typeof obj.callback === 'function') {
                            setTimeout(function () {
                                obj.callback();
                            }, settings.callbackDelay);
                        }
                    });
                })();
            }
        }
    }, settings.renderInterval);

    return {
    add: function (widget, callback, top) {
        if (typeof widget === 'undefined')
            return;

        if (typeof widget === 'string')
            widget = document.getElementById(widget);

        var obj = {
            widget: widget,
            callback: callback
        };

        if (top) 
            fbWidgets.unshift(obj);
        else {
            fbWidgets.push(obj);
        }
    },
    };
})();

Usage:

You can add the elements to the throttle all at once, or have sonar pass them in as they become visible.

// add in the element to be rendered to the end of the list   
fbThrottle.add(element);

// or you can pass in just the id
fbThrottle.add("idOfElement");

// you can pass in a callback as well
fbThrottle.add(element, function(){  
    // do something after
});

// you can add an element to the top of the list by setting the third parameter to true
fbThrottle.add(element, callback, true);

As Jakobud mentioned it is best to turn off the fb js api's automatic rendering of the widgets by turning xfbml off in your FB.init

window.FB.init({
    xfbml: false
});
Rakel answered 12/6, 2012 at 18:14 Comment(1)
I'd love to see something like this for the html5 version of the like buttonSebastian
R
0

If you are using the iFrame like button, maybe the XFBML Like button wouldn't make those calls.

You'd have to incorporate the facebook jdk including the authentication script, which seems like a lot for a few like buttons. I would only try this if it is crucial to have many like buttons instead of just one.

Rhona answered 3/2, 2012 at 22:17 Comment(7)
But if I have 30 iFrames, each one is going to have to load up the same HTML. It's gonna be similarly slow I think.Mccaleb
Thats why i said, IF you are using the iFrame like button. So i take it that you are using XFBML?Rhona
No I'm using the HTML5 option. It's seems just as slow as the XFBML.Mccaleb
hmm.... If you are using the HTML5 option, you must be authenticating through facebook, right? Is there any chance that you are running your authentication code for each button?Rhona
Well I think that Facebook's all.js that it downloads looks at each Like button's data-href url and determines how many Likes it has so it can display that number. The Like button I'm using does not show your friends who have Liked the url, so I'm not sure if it uses my Facebook cookies to determine that information or not. I don't think there is much of a way around this...Mccaleb
maybe you could clone one button with jQuery after the page load? I really don't know...Rhona
okay, so you could make one like button, and for the rest just make a regular html button that looks like a like button. Then with jquery, you click the real like button with all of the "fake" ones. The only problem with this is that if someone has already liked the url, the real like button is going to be disabled, which i guess you could check for.Rhona
V
0

That's just bad design. Every like button will create its own iFrame, and there's nothing you can do about it.

Vertebral answered 3/2, 2012 at 22:55 Comment(3)
Ah, I see what you mean. Each like button having its own iFrame is bad design by Facebook indeed.Unionist
@Inostdal Bad design by Facebook? How else would they read your session cookies?Vertebral
a good design would be them doing no such thing; no reading of session cookies or anything like thatUnionist
M
0

After much testing, this was my final solution:

Loading the Facebook all.js SDK automatically parses all Facebook Like buttons on the page. There is unfortunately no option to load the SDK without parsing existing Facebook Like buttons.

Two solutions:

  1. Load the SDK and not have any Facebook Like buttons on your page. Then, whenever there is a Like button that is visible on the screen, load in the Like button html/fbxml and then parse the markup using the SDK. I did not test this.

  2. Don't load the SDK at all. Simply use AJAX to dynamically add a Facebook iframe in wherever you want to load one up. I went with this solution.

Mccaleb answered 6/2, 2012 at 17:12 Comment(0)
I
-1

You can use parameters to make your URL slightly different and set each Like a different ref attribute.

Interdict answered 3/2, 2012 at 23:14 Comment(1)
How would this help with the number of connections?Bough

© 2022 - 2024 — McMap. All rights reserved.