Possible to find out where feature layers are being used in web applications?

29892
51
Jump to solution
02-09-2022 08:12 AM
ZachRobinson_SantaClaraCounty
Emerging Contributor

I am wondering if it is possible to easily find out which web applications in our ArcGIS Online organization are using a specific feature layer.

For example, if I delete a layer from our organization, I want to make sure I know which web maps and applications the deletion will affect. This can be difficult and tedious to search manually when an organization has many web maps and applications. 

51 Replies
Katie_Clark
MVP Alum

The short answer for right now is "no", but you can create a custom tool in a Toolbox by right clicking on the Toolbox > New > Script.

Katherine_Clark_0-1647436530767.png

Since @jcarlson was so generous with sharing his code, I'd like to share what I did to take it a step further and set up this tool so that others in my organization who didn't have programming experience could search for items. (setup for ArcGIS Pro)

When setting up the tool parameters, I entered "Web Map" and "Web Application" in the Value List I created for that parameter. This creates a drop down in the tool and ensures there won't be any typos in the user input that would break the code.

Katherine_Clark_2-1647436908885.png

Also, if anyone reads this who is completely new to Python, I wanted to point out that when setting up tools to use within Pro or ArcMap, you use arcpy.AddMessage() to print messages to the console instead of a traditional print() statement. 

And this is what the output looks like (nothing fancy) - this particular layer is only used in one web map. (side note - the time it takes to run depends on the number of items in your Organization's contents. It may run much quicker if you have fewer items to search through).

Katherine_Clark_3-1647437736336.png

This community has helped me so much throughout the years, I like to give back when I can. I hope this helps.....

 

Best,

Katherine

 

from arcgis.gis import GIS
import pandas as pd

# Log in to portal; 'home' uses the credentials used to login within Pro
gis = GIS('home')

# Set up input parameters to use in the GUI
find_id = arcpy.GetParameterAsText(0)
search_type = arcpy.GetParameterAsText(1)

find_url = gis.content.get(find_id).url

if search_type == 'Web Map':
    arcpy.AddMessage("Searching for Web Maps. This could take a few minutes...")
    # Pull list of all web maps in portal
    webmaps = gis.content.search('', item_type='Web Map', max_items=-1)

    # Return subset of map IDs which contain the service URL we're looking for
    matches = [m.id for m in webmaps if str(m.get_data()).find(find_url) > -1]

    # Create empty list to populate with results
    map_list = []

    # Check each web map for matches
    for w in webmaps:

        try:
            # Get the JSON as a string
            wdata2 = str(w.get_data())

            criteria = [
                wdata2.find(find_url) > -1,  # Check if URL is directly referenced
                any([wdata2.find(i) > -1 for i in matches])  # Check if any matching maps are in app
            ]

            # If layer is referenced directly or indirectly, append map to list
            if any(criteria):
                map_list.append(w)

        # Some apps don't have data, so we'll just skip them if they throw a TypeError
        except:
            continue

    output = pd.DataFrame([{'title': m.title, 'id': m.id, 'type': m.type} for m in map_list])
    arcpy.AddMessage(f"OUTPUT TABLE: \n \n {output}")

if search_type == 'Web Application':
    arcpy.AddMessage("Searching for Web Applications. This could take a few minutes...")
    # Pull list of all web apps in portal
    webapps = gis.content.search('', item_type='Application', max_items=-1)

    # Create empty list to populate with results
    app_list = []

    # Return subset of map IDs which contain the service URL we're looking for
    matches = [a.id for a in webapps if str(a.get_data()).find(find_url) > -1]

    # Check each web app for matches
    for w in webapps:

        try:
            # Get the JSON as a string
            wdata = str(w.get_data())

            criteria = [
                wdata.find(find_url) > -1, # Check if URL is directly referenced
                any([wdata.find(i) > -1 for i in matches]) # Check if any matching maps are in app
            ]

            # If layer is referenced directly or indirectly, append app to list
            if any(criteria):
                app_list.append(w)

        # Some apps don't have data, so we'll just skip them if they throw a TypeError
        except:
            continue

    output = pd.DataFrame([{'title':a.title, 'id':a.id, 'type':a.type} for a in app_list])
    arcpy.AddMessage(f"OUTPUT TABLE:  \n \n {output}")

 

Best,
Katie

If this answer helped you, please consider giving a kudos and/or marking as the accepted solution. Thanks!
SSMIC3038
Frequent Contributor

Thank you all for sharing this information, it's greatly appreciated and will be much used!!

OnnoKeller
Emerging Contributor

This looks really great! I am new  to python scripts though and when trying to run the tool I get an error message:

OnnoKeller_0-1681389259027.png

 

Any help on how to resolve this error would be much appreciated!

It should be noted that my maps and feature layers are in ArcGIS Online and not portal...

 

 

 

0 Kudos
jcarlson
MVP Esteemed Contributor

The API should work the same regardless of where you're searching.

Try replacing line 1 with import arcgis

Then replace line 5 with gis = arcgis.gis.GIS('home')

- Josh Carlson
Kendall County GIS
OnnoKeller
Emerging Contributor

Thanks for the quick reply and help.

Your proposed changes made the script work for me!

0 Kudos
MDB_GIS
Frequent Contributor

Katherine, 

Thank you for sharing this! It is very helpful! How long on average does it take for it to search for Web Applications for you? We have a relatively small AGOL org (<500 items) and yet it still took the tool 3.5 hours to run. The Web maps part finishes in less than a minute. I'm not sure if I've misconfigured something or if there is sosmething weird about our organization that I'm not aware of but this is a real head scratcher. 

0 Kudos
AriLukas
Regular Contributor

Hello Katherine, 

 

I realize this is an old post but i was hoping you might clarify something for me.

 

I have used it successfully to find what what Web Maps are being used but when I use it to try to find Applications I did not get any results (when i know I should). I saw in your post you showed a web map example, have you successfully been able to find apps as well? If so you, do you know what may be causing me not to find ID in any app? 

 

Thank you for all the time and effort you have put into this script

 

Best, 

Ari

0 Kudos
Katie_Clark
MVP Alum

Hi @AriLukas , I just tested using the ID of a hosted feature layer that I knew was in a web app (made with web app builder) and it worked for me. What is the exact type of application that you know the layer is in? (dashboard, instant app, etc.)

Best,
Katie

If this answer helped you, please consider giving a kudos and/or marking as the accepted solution. Thanks!
0 Kudos
Jaime_Carlino
Occasional Contributor

Hi Ari, I am experiencing the same issue. Did you ever find a solution to no output for web apps when you know you should?

0 Kudos
Big-Chill
Occasional Contributor

Thanks so much for this.  However, it does not catch items being utilized by a Web Experience.  You will need to add this (apply code where necessary).  Again, this is great stuff

# Pull list of all web experience apps
webexp = gis.content.search('', item_type='Web Experience', max_items=-1)

exp_list = []

# Check each web experience app for matches
for wx in webexp:  
    try:
        # Get the JSON as a string
        wxdata = str(wx.get_data())

        criteria = [
            wxdata.find(find_url) > -1, # Check if URL is directly referenced
            any([wxdata.find(i) > -1 for i in matches]) # Check if any matching maps are in app
        ]

        # If layer is referenced directly or indirectly, append app to list
        if any(criteria):
            exp_list.append(wx)
    
    # Some apps don't have data, so we'll just skip them if they throw a TypeError
    except:
        continue

s1 = pd.DataFrame([{'title':a.title, 'id':a.id, 'type':a.type} for a in app_list])
s2 = pd.DataFrame([{'title':b.title, 'id':b.id, 'type':b.type} for b in exp_list])

# Concatenate with original DataFrame
pd.concat([s1, s2])