Facebook Instant Games Ads

As Facebook Instant Games are becoming popular among developers. So Cocos Creator must provide the guide for monetisation and other plugins guidelines like leaderboard etc?? Is there any guide available?

I need that too. I implemented ads using pieces of code in google but i don’t know if they will work because my game is still in review :confused:

1 Like

keep searching if anything helpful lets share it

Facebook has a developer guide with API references to FBInstant if that’s what you’re missing.

1 Like

yah i check that basically i am confuse that where to add the sdk for ads. because that guide is in build?

The sdk is already including if you’re building for facebook. you just need to call the functions and have it hosted on facebook.

1 Like

thanks for replying, so i just need to add the code from fb doc and test in Facebook instant store after upload?

one more thing i just have to copy paste the javascript code in cocos creater script from documentation?

Normally I’d do a check if the library is loaded.

if(window['FBInstant]) {
  window['FBInstant'].getRewardedVideoAsync('my_placement_id',).then(function(rewardedVideo) {
  rewardedVideo.getPlacementID();});
}
1 Like

ok thanks i try it

I made my first FIG Rabbit Hole
( https://www.facebook.com/instantgames/478551539302221/)

i created a singleton that manages Facebook ads and other stuff. The code is not so clean but it works.

Summary
 import EventManager from "./EventManager";
 

window.fbAsyncInit = function() {
    FB.init({
      appId            : '478551539302221',
      autoLogAppEvents : true,
      xfbml            : true,
      version          : 'v3.2'
    });
  };

  (function(d, s, id){
     var js, fjs = d.getElementsByTagName(s)[0];
     if (d.getElementById(id)) {return;}
     js = d.createElement(s); js.id = id;
     js.src = "https://connect.facebook.net/en_US/sdk.js";
     fjs.parentNode.insertBefore(js, fjs);
   }(document, 'script', 'facebook-jssdk'));
///leaderboard






   ///ads

   const INTERSTITIAL_PLACEMENT_ID = 'PLACEMENT_ID';
   const REWARDED_PLACEMENT_ID = '<YOUR REWARDED VIDEO PLACEMENT ID>';

   var watchedInterstitials = 0;
   var watchedRewardedVideos = 0;
   var preloadedRewardedVideo = null;
   var preloadedInterstitial = null;



   function PreloadAll() {  
   
    if (typeof FBInstant === 'undefined')
    {  
        return;
    } 
 

    FBInstant.getInterstitialAdAsync(
      'PLACEMENT_ID', // Your Ad Placement Id
    ).then(function(interstitial) {
      // Load the Ad asynchronously\
      
      
      preloadedInterstitial = interstitial;
      FacebookManager.Instance.preloadedInterstitial=preloadedInterstitial;

     

      return preloadedInterstitial.loadAsync();
    }).then(function() {
      console.log('Interstitial preloaded')
    }).catch(function(err){
      console.error('Interstitial failed to preload: ' + err.message);
    });
   };

   function showInterstitial() {    
     if (typeof FBInstant === 'undefined') return;
     
    if(FacebookManager.Instance.preloadedInterstitial==null)
    {
       
        return;
    }

    FacebookManager.Instance.preloadedInterstitial.showAsync()
     .then(function() {
       // Perform post-ad success operation
       console.log(++watchedInterstitials);        
     })
     .catch(function(e) {
       console.log(e.message);
     });
   }

   function showRewardedVideo() {
    if (typeof FBInstant === 'undefined') return;

     preloadedRewardedVideo.showAsync()
     .then(function() {
       // Perform post-ad success operation
       console.log(++watchedRewardedVideos);
     }).catch(function(e) {
        console.log(e.message);
     });
   }


   
     

const {ccclass, property} = cc._decorator;

@ccclass
export default class FacebookManager extends cc.Component {

    static  Instance:FacebookManager;
      preloadedInterstitial=null    ;


      @property(cc.String)
      leaderboardName:string="";

      @property(cc.String)
      onShareUrl:string="";
      @property(cc.String)
      ShareMessage:string="";

      @property(cc.Sprite)
      sharegameImage:cc.Sprite=null;

      

    info=null;

      entry={'0':0};

  onLoad()
  {
 this. getImgBase64();


    FacebookManager.Instance=this;
    this.PreloadInterstitialAd();
 
  }

  StartFacebookInstant () {
    if (typeof FBInstant === 'undefined') return;
    
    
    this.info = {
        contextID: FBInstant.context.getID(), // 游戏 ID
        contextType: FBInstant.context.getType(), // 游戏类型
        locale: FBInstant.getLocale(),  // 地区
        platform: FBInstant.getPlatform(),// 平台
        sdkVersion: FBInstant.getSDKVersion(),// SDK 版本号
    }
   


}

start()
{

 //   this.GetScreenshot(null);

this.StartFacebookInstant();

this.entry=this.GetLeaderBoardPlayerData();
 
 
}

  WriteDebugText(text)
  {

     
     EventManager.Event.emit('OnDebugThrowException',text); 

  }

  PreloadInterstitialAd()
  {

    PreloadAll();
  }


    ShowInterstitialAd()
    {
       
        showInterstitial();
  
    }
     


    SetLeaderBoardScore(score:number)
    {
        if (typeof FBInstant === 'undefined') return;

        let contextId=FBInstant.context.getID();
        console.log(FBInstant.context);

        FBInstant
    .getLeaderboardAsync(this.leaderboardName )
    .then(leaderboard => {
    console.log(leaderboard.getName());
    return leaderboard.setScoreAsync(score );
    })
    .then(() => console.log('Score saved'))
    .catch(error => console.error(error));

    }


  GetLeaderboard(callback,  leaderboardSize=10)
  {   if (typeof FBInstant === 'undefined') return null;
    FBInstant
    .getLeaderboardAsync(this.leaderboardName )
    .then(leaderboard => leaderboard.getEntriesAsync(leaderboardSize, 0))
    .then(callback).catch(error => console.error(error));
}

GetLeaderBoardPlayerData()
{ 
    if (typeof FBInstant === 'undefined')
    {
      EventManager.Event.emit('OnLeaderboardLoaded',null);
      return null;
    } 
    FBInstant.getLeaderboardAsync(this.leaderboardName)
    .then(function(leaderboard) {
     
     return leaderboard.getPlayerEntryAsync();
    })
    .then(function(entry) {
     
     
      EventManager.Event.emit('OnLeaderboardLoaded',entry)
      return entry;

      
    })
     .catch(error => {
      console.error(error) ;
    EventManager.Event.emit('OnLeaderboardLoaded',null)
  }
    );
}
 
PostLeaderboardUpdate()
{  if (typeof FBInstant === 'undefined') return null;
    FBInstant.updateAsync({
        action: 'LEADERBOARD',
        name: this.leaderboardName+'.' +  FBInstant.context.getID()
      })
        .then(() => console.log('Update Posted'))
        .catch(error => console.error(error));
}

ShareInstant(screenshotCamera)
{
 
   
  this.onShareGame(screenshotCamera);

}

    onLogin () {
        if (typeof FB === 'undefined') return;
        FB.login((response) => {
            if (response.authResponse) {
            console.log('Welcome!  Fetching your information.... ');
            FB.api('/me', (response) => {
                this.outTips.string = 'Good to see you, ' + response.name + '.' + response.id;
        });
        }
    else {
            this.outTips.string = 'User cancelled login or did not fully authorize.';
        }
    });
    } 
    onLogout () {
        if (typeof FB === 'undefined') return;
        FB.logout((response) => {
            this.outTips.string = 'logout';
        console.log(response);
    });
    } 
    onShareGame (screenshotCamera) {
      if (typeof FBInstant === 'undefined') return;

      let shareImg=null ;
 

        if(screenshotCamera!=null)
        {
          shareImg=  this.GetScreenshot(screenshotCamera);

        }else
        {
            shareImg=this.getImgBase64();
        }
     

      FBInstant.shareAsync({
          intent: 'REQUEST',
          image: shareImg,
          text: this.ShareMessage,
          data: {myReplayData: '...'},
      }) 
  }
  getImgBase64 () {
  /*
  let sp = this.sharegameImage ;
  
  let target = cc.find('Canvas');
  let width = 960, height = 640;
  let renderTexture = new cc.RenderTexture();
  
  //
  let canvas = document.createElement('canvas');
  let ctx = canvas.getContext('2d');
  let gl = cc.game._renderContext;

  canvas.width = width;
  canvas.height = height;
  
      let buffer = gl.createFramebuffer();
      gl.bindFramebuffer(gl.FRAMEBUFFER, buffer);
 
      renderTexture.initWithSize(cc.visibleRect.width, cc.visibleRect.height, gl.STENCIL_INDEX8);
    
      renderTexture.initWithElement(sp.spriteFrame.nativeUrl);

      let texture = renderTexture._texture._glID;
      gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
      let data = new Uint8Array(width * height * 4);
      gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
      let rowBytes = width * 4;
      for (let row = 0; row < height; row++) {
          let srow = height - 1 - row;
          let data2 = new Uint8ClampedArray(data.buffer, srow * width * 4, rowBytes);
          let imageData = new ImageData(data2, width, 1);
          ctx.putImageData(imageData, 0, row);
      }
  
  return canvas.toDataURL('image/png');
 */
}
   
 
GetScreenshot(cameraRef)
{
    let node = new cc.Node();
    node.parent = cc.director.getScene();
    let camera = node.addComponent(cc.Camera);
    
    // Set the CullingMask of the screenshot you want
    camera.cullingMask =cameraRef.cullingMask;

    node.setParent(cameraRef.node.parent);
    node.position=cameraRef.node.position;
    
    // Create a new RenderTexture and set this new RenderTexture to the camera's targetTexture so that the camera content will be rendered to this new RenderTexture
    let texture = new cc.RenderTexture();
    let gl = cc.game._renderContext;
    let width = cc.visibleRect.width;
    let height = cc.visibleRect.height;

    // If the Mask component is not included in the screenshot, you don't need to pass the third parameter.
    texture.initWithSize(width,height);
    camera.targetTexture = texture;
     
    // Render the camera once, updating the content once into RenderTexture
    camera.render();
  
    // This allows the data to be obtained from the rendertexture.
    let data = texture.readPixels();
    
    // Then you can manipulate the data.
    let canvas = document.createElement('canvas');
    let ctx = canvas.getContext('2d');
    canvas.width = texture.width;
    canvas.height = texture.height;
    
    let rowBytes = width * 4;
    for (let row = 0; row < height; row++) {
        let srow = height - 1 - row;
        let imageData = ctx.createImageData(width, 1);
        let start = srow*width*4;
        for (let i = 0; i < rowBytes; i++) {
            imageData.data[i] = data[start+i];
        }
    
        ctx.putImageData(imageData, 0, row);
    }
    
    let dataURL = canvas.toDataURL("image/jpeg");
   // let img = document.createElement("img");
    //img.src = dataURL;



    return dataURL;

}
    onShare () {
        if (typeof FB === 'undefined') return;
        FB.ui({
            method: 'share',
            href: this.onShareUrl,
        }, (response) => {
            console.log(response);
        });
    } 

    onAppRequests () {
        if (typeof FB === 'undefined') return;
        FB.ui({
            method: 'apprequests',
            message: 'Hello !!!',
        }, (response) => {
            this.outTips.string = JSON.stringify(response);
    });
    }
}
1 Like

thanks for sharing.
can you share the steps if possible.

i mean any sdk imported?
or simple typescript code, all code is in cocos creator script ? and thats it :slight_smile:

No Sdk.
EventManager is custom event handler i made, you can delete it or make one yourself.
Add this script to a new node in scene.

1 Like

yup worked. . checking it. :slight_smile: thanks

move on. it would work for you :slight_smile:

Script is not neat but functions well

i did follow this and its work, thanks

HI Hammadzahid
Did you call facebook ads success?
I was try but still not luck.
Could you help me?

Brother i want to guide you to the official git repository

They provided very simple description on it.

1 Like

Thank you bro.
I got it

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.