Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Mr-Musa
Explorer
16,595
Currently SAP didn’t provide any tools to track the usage of the application (Tiles) in the launchpad. I came across several option & suggestions but none of them were really giving the real usages.

Example:
SE38–>Enter Report name /IWFND/R_METERING_VIEW

This report will show the usage of the OData service. Fiori apps will consume the service several times during execution and you can’t relate from which app this call is coming from.


 


So I decided to try utilize the following to achieve my goal:



  • Use Web APIs Windows hashchange event which will help us to monitor the target mapping changes.

  • Use FLP API sap.ushell.services.LaunchPage (ondemand.com) to get  user’s tiles & groups & catalogs.

  • Fiori launchpad plugin to run my tracking script.

  • Custom Odata service to post user tracking logs

  • Table to store the logs

  • Use of standard table SUI_TM_MM_APP to get some extra information of the used app that is not available in the sap.ushell.services.LaunchPage services.


 

 

This way it will log every app had been used even HTML GUI , Webdynpro , Custom SAPUI5 apps maintained as target mapping.

It will exclude the navigation that change the hash within the the same app, so we will not over record the usage of an app.

 

 

 

 

 

Let’s start now :



1- WEBIDE Create a plugin, please refer to the following for detailed steps Creating SAP Fiori Launchpad Plugins in SAP Web IDE - SAP Help Portal



  • Add below code to the plugin allowing with predefined code.
    		init: function () {
    var oComponent = this;
    var rendererPromise = this._getRenderer();

    //Trakcing the usage is working upon 'hashchange' event triggers
    window.addEventListener("hashchange", oComponent._onHashChange.bind(this), true);

    //Waiting for the FLP shell container to be ready to start plugin methods
    rendererPromise.then(function (oRenderer) {
    oComponent._onFioriTracker();
    oComponent._initTrackerOdataService();
    });

    },

    _initTrackerOdataService: function() {
    //initialization of Tracking service (OData) --> ZFLPTRACKING
    var sServiceUrl = '/sap/opu/odata/sap/ZFLPTRACKING_SRV/';
    var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl, true);
    oModel.setUseBatch(false);
    this.setModel(oModel);
    },

    _onFioriTracker: function(oEvent) {
    // Bullding the array of the tiles once the FLP is loaded
    // The belwo array will be used to be refreced to get the tiles details upon clicking of a tile
    this.UserTiles = [];

    //Custom Tiles had to be treated diffrently to get its informaiton
    //it's pushed inside the below array to be treated thend again pushed back to this.UserTiles array
    this.MenuTileArray = [];



    //Here we will get the tiles from groups & catalogs then start collecting required
    //information (title , catalog id , group id , target mapping .. etc)
    sap.ushell.Container.getService("LaunchPage").getGroups().then(function(aGroups) {
    sap.ushell.Container.getService("LaunchPage").getCatalogs().done(function (oCatalogs) {
    for (var i = 0; i < aGroups.length; i++) {
    var aGrpTiles = sap.ushell.Container.getService("LaunchPage").getGroupTiles(aGroups[i]);

    for (var j = 0; j < aGrpTiles.length; j++) {
    var sTileTitle = sap.ushell.Container.getService("LaunchPage").getTileTitle(aGrpTiles[j]);
    if(sTileTitle === "App Launcher – Static")
    {
    if( sap.ushell.Container.getService("LaunchPage").getCatalogTilePreviewSubtitle(aGrpTiles[j]) ){
    sTileTitle = sap.ushell.Container.getService("LaunchPage").getCatalogTilePreviewTitle(aGrpTiles[j])
    + " ( "
    + sap.ushell.Container.getService("LaunchPage").getCatalogTilePreviewSubtitle(aGrpTiles[j])
    + " )";
    }else{
    sTileTitle = sap.ushell.Container.getService("LaunchPage").getCatalogTilePreviewTitle(aGrpTiles[j]);
    }

    }
    var sTileTarget = sap.ushell.Container.getService("LaunchPage").getCatalogTileTargetURL(aGrpTiles[j]);
    this.sTileCatalogeId = sap.ushell.Container.getService("LaunchPage").getCatalogTileId(aGrpTiles[j]);



    var aCatalogTile = oCatalogs.filter(function (c) {
    return this.sTileCatalogeId.includes(c.id);
    }.bind(this));

    if(aCatalogTile.length > 0){
    var sTileCataloge = aCatalogTile[0].title;
    }else{
    var sTileCataloge = sap.ushell.Container.getService("LaunchPage").getCatalogTileTitle(aGrpTiles[j]);
    }



    if(sTileTitle === "Menu Custom Tile"){
    //Handle Menu Tile: push them in array to handle them later
    this.MenuTileArray.push(aGrpTiles[j]);

    }else{
    this.UserTiles.push({
    tileTitle : sTileTitle,
    catalogeId : this.sTileCatalogeId,
    cataloge : sTileCataloge,
    groupTitle : aGroups[i].getTitle(),
    groupId : aGroups[i].getId(),
    target : sTileTarget
    });

    }//-------------if(sTileTitle === "Custom Tile"){

    sTileTitle = "";
    sTileTarget = "";
    this.sTileCatalogeId = "";
    sTileCataloge = "";

    }//----------for (var j = 0; j < aGrpTiles.length; j++) {
    aGrpTiles = [];
    }//-------for (var i = 0; i < aGroups.length; i++) {


    //Handle Menu Tile
    for(var x=0; x <this.MenuTileArray; x++ ){
    sap.ushell.Container.getService("LaunchPage").getTileView(this.MenuTileArray[x]).then(function(oTileView) {
    var tileApi = oTileView.getViewData().chip;
    var tileConfigurationData = sap.ushell.components.tiles.utilsRT.getConfiguration(tileApi);

    if(tileConfigurationData){
    sTileTitle = tileConfigurationData.display_title_text;
    this.UserTiles.push({
    tileTitle : sTileTitle,
    catalogeId : this.sTileCatalogeId,
    cataloge : sTileCataloge,
    groupTitle : aGroups[i].getTitle(),
    groupId : aGroups[i].getId(),
    target : sTileTarget
    });
    } //---------if(tileConfigurationData){
    }.bind(this)); //--------sap.ushell.Container.getService("LaunchPage").getTileView(aGrpTiles[j]).then(function(oTileView) {
    }


    window.dispatchEvent(new HashChangeEvent("hashchange"));

    }.bind(this)); //--- sap.ushell.Container.getService("LaunchPage").getCatalogs().done(function (oCatalogs) {
    }.bind(this)); //-- sap.ushell.Container.getService("LaunchPage").getGroups().then(function(aGroups) {
    },

    _onHashChange: function(oEvent) {
    //This method will handle the target mappinng change 'HASH'
    var oComponent = this;
    var sOldHash = sap.ushell.utils.getBasicHash(this._getHashFromURL(oEvent.oldURL));
    var sNewHash = sap.ushell.utils.getBasicHash(this._getHashFromURL(oEvent.newURL));
    var tile = [];


    //handle open in new tab or by direct link
    if(sOldHash == "" && sNewHash == ""){
    sNewHash = sap.ushell.utils.getBasicHash(window.location.hash);
    }

    //handle the change of URL while navigation within the app or within same target mapping
    if (sOldHash !== sNewHash) {
    this.sHash = sNewHash;

    tile = this.UserTiles.filter(function(o) {
    if (o.target) {
    return sap.ushell.utils.getBasicHash(o.target).indexOf(sap.ushell.utils.getBasicHash(oComponent.sHash)) === 0;
    }
    });

    if(sNewHash === "Shell-home" && tile.length === 0 && true ){ // This to consider or not to consider the FLP home usage
    tile.tileTitle = "Fiori Launchpad Access";
    tile.cataloge = "";
    tile.catalogeId = "";
    tile.groupId = "";
    tile.groupTitle = "";
    tile.target = "#Shell-home";
    this._postTracking(tile);

    }else{
    this._postTracking(tile[0]);
    }

    }
    },

    _getHashFromURL: function(URL) {
    return URL.substring(URL.indexOf('#'));
    },


    _postTracking: function(tile) {
    //Posting the application usage recored to backend
    if(tile){
    var oData = {
    TrackNo : "", // <--- dummy,
    Tile : tile.tileTitle,
    Cataloge : tile.cataloge,
    Catalogeid : tile.catalogeId,
    Tgroupid : tile.groupId,
    Tgroup : tile.groupTitle,
    Target : tile.target
    };

    this.getModel().create("/TrackSet", oData, {
    success: function(oSuccess) {

    }.bind(this),
    error: function(oError) {

    }.bind(this)
    });
    }
    },​



As I mentioned we use the hashchange event to track the used app. and to get the app information at the initialization I’m building an array of all users tiles along with available information (Tile Title, cataloge,group, target(#SemanticObject-Action), …etc) and a method to handle the change hash then get the clicked tile form our array then prepare the data to be posted at the back end.

*Best thing is debuge the code to have full understanding for the solution and if you have any question please feel free.

 

 

  • Deploy the BSP application.


 

 

 

2- Create Shell plugin Target Mapping in the launchpad designer. Activating Plug-Ins on the ABAP Platform - SAP Help Portal


 

3- Assignee the catalog which contain the shell plugin to a role. And assign the role to people who you want to track.


 

 

4- Create Table to hole data (Below is suggested structure):


MANDT	MANDT	CLNT	3	0	0	Client
TRACK_NO GUID RAW 16 0 0 Globally Unique Identifier
FIORI_ID /UI2/AD_MM_FIORI_ID CHAR 20 0 0 SAP Fiori ID
TILE CHAR 100 0 0 Tile
FLP_USER SYUNAME CHAR 12 0 0 User Name
FDATE SYDATUM DATS 8 0 0 System Date
FTIME SYUZEIT TIMS 6 0 0 System Time
CATALOGEID /UI2/PAGE_ID CHAR 100 0 0 Catalog ID
CATALOGE CHAR 200 0 0 Cataloge Title
TGROUPID /UI2/GROUP_ID CHAR 100 0 0 Group ID
TGROUP CHAR 200 0 0 Group Title
TARGET CHAR 200 0 0 Target
SEMANTICOBJECT CHAR 40 0 0 Semantic Object
ACTION CHAR 40 0 0 Action
PARAMETERS CHAR 200 0 0 Parameters

 

 

 

5- Create Odata Service : and implement the create method to post the logs.


Below is the create entity
    DATA : ls_output       LIKE er_entity,
ls_zflptracking TYPE zflptracking.

io_data_provider->read_entry_data(
IMPORTING es_data = ls_output
).

MOVE-CORRESPONDING ls_output TO ls_zflptracking.

CALL FUNCTION 'GUID_CREATE'
IMPORTING
ev_guid_16 = ls_zflptracking-track_no
* EV_GUID_22 =
* EV_GUID_32 =
.


ls_zflptracking-flp_user = sy-uname.
ls_zflptracking-fdate = sy-datum.
ls_zflptracking-ftime = sy-uzeit.


* X-SAP-UI2-PAGE:X-SAP-UI2-CATALOGPAGE:SAP_SFIN_BC_AA_DOC_PROC:00O2TPKTQCDUX5DENYJNYYXTU
SPLIT ls_zflptracking-catalogeid AT ':' INTO TABLE DATA(lt_segments).
SPLIT ls_zflptracking-target AT '#' INTO TABLE DATA(lt_target).
READ TABLE lt_target INTO DATA(lv_targetval) INDEX 2.
SPLIT lv_targetval AT '-' INTO TABLE DATA(lt_semact).
READ TABLE lt_semact INTO DATA(lv_action2) INDEX 2.
SPLIT lv_action2 AT '?' INTO TABLE DATA(lt_action).
READ TABLE lt_action INTO DATA(lv_action) INDEX 1.
READ TABLE lt_semact INTO DATA(lv_semobj) INDEX 1.

ls_zflptracking-semanticobject = lv_semobj.
ls_zflptracking-action = lv_action.
ls_zflptracking-catalogeid = lt_segments[ 3 ].



"Get FIORI APP ID
SELECT SINGLE fiori_id FROM sui_tm_mm_app
INTO @DATA(lv_fiori_id)
WHERE sem_obj = @lv_semobj AND sem_act = @lv_action.
IF sy-subrc = 0 and lv_fiori_id is NOT INITIAL.
ls_zflptracking-fiori_id = lv_fiori_id.
ENDIF.

INSERT zflptracking FROM ls_zflptracking.

 

 

6- You are ready to go.


 

 

Here is my ALP Report based CDS query.


 

 

 

Ideas to enhance the plugin:



  • Add switch on/off flag

  • cash the array of the tile in the browser cashe


 

looking to hear all your suggestions to improve:)

 

 

Thanks to my friend for his help and contribution: vivek.anandhan


 
15 Comments
Labels in this area