Create Survey123 URLs using Arcade

5345
7
11-23-2020 04:09 PM

Create Survey123 URLs using Arcade

Using URLs to open Survey123 from Collector or Explorer pop-ups is a popular integration.  There are a couple of limitations that are present due to the pop-up being designed primarily to produce text that a person reads:

  • Number formatting is localized based on the user's language and locale settings.  This can cause issues if a user's locale uses a comma as the decimal separator (like most of continental Europe and South America) or includes grouping characters (for example, the thousands comma separator in English).
  • Dates are displayed as localized text.
  • Text may include characters like spaces or ampersands (&) which interfere with the ability to process a URL.
  • You can't access the feature's geometry information to pass into Survey123.

One way to address these limitations is to use ArcGIS Arcade to generate the URL. Arcade is a general scripting language that can be used to create custom information in a pop-up, among other tasks. 

The Basics: Using the UrlEncode function

The first Arcade function to know is the UrlEncode function. Using this function will:

  • Provide a standard data representation of numbers and dates
  • Encode special characters so that they can be used in URLs
  • Automatically join parameters together with ampersands

The pattern is to create a dictionary (object) of parameter:value with all the URL parameters you want to include. This will likely include itemId (the form you want to open), field:<question_name> (to populate a question with data), center (to specify a point geometry - more on this below!). Earlier this year, Survey123 also added several new URL parameters, including allowing a user to open an existing record for editing. Visit the URL Parameters documentation to learn more!

The UrlEncode function creates the parameters that occur after the question mark (?) in a URL; you need to join it with the URL's first part that specifies which application to open (arcgis-survey123:// or https://survey123.arcgis.app for the Survey123 field app; https://survey123.arcgis.com/share/<itemId> for the web app).  Here's an example of an arcade function to create a full URL to open a form:

var urlsource ='arcgis-survey123://?';
var params = {
  itemID:'36ff9e8c13e042a58cfce4ad87f55d19',
  center: '43.567,-117.380'
};
return urlsource  + UrlEncode(params);

This will return

arcgis-survey123://?center=43.567%2C-117.380&itemID=36ff9e8c13e042a58cfce4ad87f55d19

Accessing feature Information (attributes & geometry)

Arcade also provides access to the pop-up's feature, including both attributes and geometry. If the feature is a point, that allows us to get the x and y values without needing them to be stored in the attribute table

Field values     $feature["asset_id"]
X/Y values       Geometry($feature).x

Note that the x and y values will be in the map's spatial reference; Survey123 requires WGS84 latitude/longitude.  Esri's default basemaps use the Web Mercator projection; you will need to convert the values:

function WebMercatorToWGS84 (x, y) {
    var lon = (x / 20037508.34) * 180;
    var lat = (y / 20037508.34) * 180;
    lat = 180/PI * (2 * Atan(Exp(lat * PI / 180)) - PI / 2);
    return {
        y: lat,
        x: lon
    }
}

Combining that with UrlEncode will result in an Arcade expression of:

function WebMercatorToWGS84 (x, y) {
    var lon = (x / 20037508.34) * 180;
    var lat = (y / 20037508.34) * 180;
    lat = 180/PI * (2 * Atan(Exp(lat * PI / 180)) - PI / 2);

    return {
        y: lat,
        x: lon
    }
}
var urlsource ='arcgis-survey123://?';
var geom = Geometry($feature)
var coords =  WebMercatorToWGS84(geom.x, geom.y)
var params = {
  itemID:'36ff9e8c13e042a58cfce4ad87f55d19',
  field:asset_id: $feature["asset_id"],
  center: coords.y + "," coords.x
};
return urlsource  + UrlEncode(params);

One thing to note about the geometry is that it may be generalized based on the zoom level and not be the true geometry stored in the dataset. While this shouldn't be an issue with points, this may become more significant with lines and polygons.

Accessing line and polygon vertices

In addition to points, we can also include line and polygon information in the URL. There are a few limitations to note:

  • Only simple geometries can be passed via URL parameters. Multi-part geometries, polygons with holes are not supported.
  • The generalization mentioned above may offset vertices from their true location, changing the shape and angles.

The format needed to pass a line or polygon is a sequence of:

lat1 lon1;lat2 lon2;lat3 lon3;...

This is a different format than the format Arcade presents the vertices.  Lines have a `paths` property and polygons have a `rings` property; these are both arrays that hold individual path/ring (line/polygon) information. Each path/ring is an array of the coordinates; the following function converts a path/ring to the text list of coordinates Survey123 requires:

function coordsToString(coordSequence) {
    var coordTextParts = []
    var idx = 0;
    for (var c in coordSequence) {
    // Get the point in the sequence
        var thisPoint = coordSequence[c];
        // Add the <lat> <lon> string to the output list
        coordTextParts[idx] = Concatenate(thisPoint.y, " ", thisPoint.x);
       
++idx;

    }
    // Join the coordinate strings together with ;
    return Concatenate(coordTextParts, ";")
}

Determining which path or ring to use can be tricky. For very simple shapes, you may be able to use the first (i.e., paths[0] or rings[0]).  You also could try to join paths together, though that may lead to unexpected shapes if the paths aren't in sequence.

This web map has some examples of Arcade generated links; I've included the Arcade functions used in the attached file.

 

Attachments
Comments

Hi @JamesTedrick , I've come across your post from a little over a year ago. I have S123 form URLs passing attributes from Field Maps to S123. I have this set up as html at the moment. I'd like to transition this over to arcade. I am still very early in my Arcade journey. I've tried to replicate what you've done in your post, but have gotten stuck because I want to pass the GlobalID over to the GUID.

var ConsentForm1url = 'https://survey123.arcgis.app/?';
var params = {
itemID:'5381969754724e5cb044ae94080f8c0c',
field:GlobalID: $feature["GUID"],
//^This is where I'm having the issue.
};
return ConsentForm1url + UrlEncode(params);
//Possible to have the url appear as ConsentForm1 on the front end?
//I want to do this for four different forms and then create a new field via pop-ups that shows the url based off of the client.

 

Hi @JamesTedrick,

Thanks for this really useful article. I'm having an issue passing field parameters as you have in your example. Where you have field:asset_id: $feature["asset_id"] I keep getting the error Unexpected token :.

It doesn't like the second colon so I was wondering how it's possible to define field parameters in a dictionary in this way?

Thanks

Anthony

Sorry, ignore my last comment. I've just looked at your web map example and can see in there how you've enclosed the field parameter and field name in inverted commas e.g. "field:asset_id": $feature["asset_id"], which seems to do the trick. Thanks!

Hi @JamesTedrick 

Is it possible to use Arcade to pre-populate repeat sections? 

 

Hi Ana,

Obviously James is the expert on this but I don't think it's possible to populate questions in repeats using urls. It certainly says that here and see below.

AnthonyJones5_0-1668779770836.png

One way around it though is to build a separate form on top of your repeat. This was you could populate questions for existing repeats or generate a url to create new features in the repeat. This may not work in your situation but is a workaround I use in order to populate repeats whilst keeping the data all under one parent layer, which helps with report generation.

Cheers

Anthony 

@JamesTedrick,

Thank you for this post. I've attempted to use arcade to pass attributes and geometry to Survey123 but my Arcade expression won't work. I'm getting an error that says invalid variable assignment. Any help you can give me would be appreciated.

PlANNADMIN_0-1679797546828.png

 

@JamesTedrick Just FYI there appears to be a couple of errors in this sample. Was receiving invalid variable errors.

var params = {
  itemID:'36ff9e8c13e042a58cfce4ad87f55d19',
  field:asset_id: $feature["asset_id"],
  center: coords.y + "," coords.x
};
return urlsource  + UrlEncode(params);

This works:

var params = {
  itemID:'36ff9e8c13e042a58cfce4ad87f55d19',
  field:"asset_id:" + $feature["asset_id"],
  center: coords.y + "," + coords.x
};
return urlsource  + UrlEncode(params);

Version history
Last update:
‎11-23-2020 04:09 PM
Updated by: