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

20346
42
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. 

42 Replies
EmmaCurran18
Occasional Contributor

@jcarlson I am getting the same error as @HaThach1 . Have we found a solution to this? I haven't been able to get something to work.

0 Kudos
WesleyMills
Emerging Contributor

I know this is an older post I found it yesterday and had the same problem as you. Izk222 already bypassed the issue with a different technique but for this specific script:

The issue is that you need to run the same 'for loop' for web maps as you do the web apps. "matches" only contains a string of id numbers for the maps. It doesn't have a title, id, or type. Running the loop captures that data to send to the pandas data frame.
 

 

From the top for catching apps and web maps:

from arcgis.gis import GIS
import pandas as pd
 
# Log in to portal; prompts for PW automatically
gis = GIS('your portal url including https', 'your username')
 
# Layer ID to search for and its URL
find_id = 'layer id number'
find_url = gis.content.get(find_id).url
print(find_url)
 
# 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
m_matches = [m.id for m in webmaps if str(m.get_data()).find(find_url) > -1]
 
# print web map ids that use this layer for sanity check
for i in m_matches:
    print(i)
 
# create list to store target maps
map_list = []

for w in webmaps: # for every map in your portal
    
    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):
            map_list.append(w)
    
    # Some apps don't have data, so we'll just skip them if they throw a TypeError
    except:
        continue
 
# Pull list of all web apps in portal
webapps = gis.content.search('', item_type='Application', max_items=-1)

app_matches = [a.id for a in webapps if str(a.get_data()).find(find_url) > -1]
 
# print web app ids that use this layer for sanity check
for i in app_matches:
    print(i)
 
# Create empty list to populate with results
app_list = []

# 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
 
# display data
print('apps:')
pd.DataFrame([{'title':a.title, 'id':a.id, 'type':a.type} for a in app_list])
 
# display data
print('web maps:')
pd.DataFrame([{'title':m.title, 'id':m.id, 'type':m.type} for m in map_list])

 

Jaime_Carlino
Occasional Contributor

Hey Wesley, thank you for compiling bits from previous posts and putting them together here. This seems to be working well for web maps, but I am not getting any output for web apps. I am using service layer IDs that I know are used in web maps that were then used in applications like a dashboard. I appreciated the sanity checks for both web maps and web apps, which was my first indication that something is going on with the web apps. Any insight?

0 Kudos
GITTeam
New Contributor

Hey Wesley, thank you for compiling bits from previous posts and putting them together here. This seems to be working well for web maps, but I am not getting any output for web apps. I am using service layer IDs that I know are used in web maps that were then used in applications like a dashboard. I appreciated the sanity checks for both web maps and web apps, which was my first indication that something is going on with the web apps. Any insight?

0 Kudos
MDB_GIS
Frequent Contributor

Hey, 

Just curious, but how long should it take this tool to run? We have a fairly small AGOL org with less than 500 items but the tool has been running for about 15 minutes so far. This  is my second attempt at running it. 

I'm running it in the Python window and it appears to be running, but it is just bogged down somewhere. 

 

0 Kudos
awgeezrick
Regular Contributor

Thanks for sharing Josh. Came in massively handy for me today. 

LesleyHope
Emerging Contributor

Hi, this may be a stupid question but I've been going round in circles for what feels like days - where am I putting this code?

Thanks,

Lesley

0 Kudos
WesleyMills
Emerging Contributor

You can run it into arcgis notebooks. In pro: click analysis on the top ribbon, click the drop down arrow for python toward the top left of the ribbon, click python notebook.

0 Kudos
NavaSheer
Regular Contributor

Is there any other way to do this without Python or other coding?  I am not a developer but really need this tool.  Geo Jobe offers it in Pro for a fee, but would appreciate if ESRI would offer for free!

0 Kudos
Katie_Clark
MVP Regular Contributor

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


“The goal is not simply to ‘work hard, play hard.’ The goal is to make our work and our play indistinguishable.”
- Simon Sinek