Skip to content

Survey123 Field App on mobile device

An overview of developer integrations for the ArcGIS Survey123 Field App.

The ArcGIS Survey123 Field App is a native mobile application designed for field data collection. While the Field App has limited programmatic extension capabilities, it can be integrated with external systems through data access, URL schemes, and webhooks. This topic covers the practical approaches for integrating the Field App into your development workflows.

The Survey123 Field App has limited programmatic extension capabilities but you can configure surveys to work better with your workflows. The Field App is designed as a data collection tool rather than a customizable platform, which means most integration happens through data access and URL schemes rather than direct app modification.

LimitationExplanationAlternative
Custom JavaScriptField App does not support custom JavaScript functionsUse XLSForm calculations or web app for complex logic
Plugin ExtensionsNo plugin architecture for custom functionalityBuild custom mobile apps using ArcGIS Maps SDKs
Direct API AccessField App does not expose APIs for external integrationUse Feature Layer REST API to access survey data
Custom UI ComponentsCannot modify the Field App's user interfaceUse Survey123 Web Designer for custom web forms

Data integration

The Field App collects survey responses and stores them in ArcGIS Feature Layers. You can access this data programmatically using the ArcGIS REST API.

Accessing survey data

The primary way to integrate with the Survey123 Field App is through the data it collects. Survey responses are stored in ArcGIS Feature Layers and can be accessed programmatically using the ArcGIS REST API.

MethodPurposeUse Cases
Feature Layer REST APIDirect access to survey dataCustom reporting, data analysis, real-time dashboards
ArcGIS API for PythonAutomated data processingWorkflow automation, data analysis, report generation
ArcGIS Maps SDKsCustom applicationsBuilding custom data visualization and management tools

You can use the ArcGIS API for Python to access survey data programmatically and analyze survey responses. Below is an example of how to access survey data.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from arcgis.gis import GIS
from arcgis.features import FeatureLayer

try:
    # Connect to ArcGIS Online
    gis = GIS("https://www.arcgis.com", username="your_username", password="your_password")

    # Access survey data through feature layer
    survey_layer = FeatureLayer("https://services.arcgis.com/.../FeatureServer/0", gis=gis)
    responses = survey_layer.query()

    # Process and analyze data
    if responses.features:
        for feature in responses.features:
            # Custom data processing logic
            attributes = feature.attributes
            geometry = feature.geometry
            print(f"Processing survey ID: {attributes.get('objectid')}")
            # Add your custom processing here
    else:
        print("No survey responses found")

except Exception as e:
    print(f"Error accessing survey data: {str(e)}")

You can monitor survey submissions using webhooks for real-time notifications. See the Webhooks for real-time integration section below for implementation details.

Alternatively, you can poll for new submissions using the ArcGIS REST API:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Poll for new survey submissions
function checkForNewSubmissions(featureLayerUrl, token, lastCheckTime) {
  const queryUrl = `${featureLayerUrl}/query`;
  const params = new URLSearchParams({
    where: `CreationDate > timestamp '${lastCheckTime}'`,
    outFields: '*',
    returnGeometry: true,
    f: 'json',
    token: token
  });

  fetch(`${queryUrl}?${params}`)
    .then(response => response.json())
    .then(data => {
      if (data.features && data.features.length > 0) {
        // Process new survey submissions
        data.features.forEach(feature => {
          processNewSubmission(feature.attributes);
        });
      }
    })
    .catch(error => {
      console.error('Error checking for submissions:', error);
    });
}

// Poll every 30 seconds
setInterval(() => {
  checkForNewSubmissions(
    "https://services.arcgis.com/.../FeatureServer/0",
    "YOUR_TOKEN",
    new Date(Date.now() - 30000).toISOString()
  );
}, 30000);

App integration

You can integrate the Field App with other applications using URL schemes. Below are examples of how to integrate the Field App with other applications using URL schemes.

URL schemes and deep linking

The Survey123 Field App supports two methods for launching surveys from other applications:

App Link (Recommended):

URL FormatPurposeParameters
https://survey123.arcgis.app?itemID={surveyId}Launch specific survey (cross-platform)itemID, callback, field parameters
https://survey123.arcgis.app?itemID={surveyId}&callback={url}Launch survey with return URLPre-populate fields and return to calling app
https://survey123.arcgis.app?itemID={surveyId}&{field}={value}Launch survey with pre-filled dataCustom field values (URL-encoded)

Custom URL Scheme (Alternative):

URL FormatPurposeNotes
arcgis-survey123://?itemID={surveyId}Launch specific survey (iOS/Android)Requires app installed; may not work on all platforms

Web application integration

You can integrate the Field App with other applications using URL schemes. Below are examples of how to integrate the Field App with other applications using URL schemes.

ArcGIS Maps SDK for JavaScriptArcGIS Maps SDK for JavaScriptArcGIS Maps SDK for SwiftArcGIS Maps SDK for Android
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Launch Survey123 Field App from web application
function launchSurveyApp(surveyId, prefillData) {
  // Use app link format for better cross-platform compatibility
  const baseUrl = "https://survey123.arcgis.app";
  const params = new URLSearchParams({
      itemID: surveyId,
      callback: window.location.href
  });

  // Add prefill data
  if (prefillData) {
      for (const key in prefillData) {
          params.append(key, prefillData[key]);
      }
  }

  const surveyUrl = baseUrl + "?" + params.toString();

  // Open the survey
  window.location.href = surveyUrl;

  // Optional: Detect if app is not installed (mobile only)
  setTimeout(() => {
      if (document.hidden) {
          // App opened successfully
          console.log("Survey app launched");
      } else {
          // On mobile, redirect to app store if app not installed
          const userAgent = navigator.userAgent || navigator.vendor || window.opera;
          if (/android/i.test(userAgent)) {
              window.location.href = "https://play.google.com/store/apps/details?id=com.esri.survey123";
          } else if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
              window.location.href = "https://apps.apple.com/app/arcgis-survey123/id993015031";
          }
      }
  }, 1500);
}

// Example usage
launchSurveyApp("abc123def456ghi789", {
  "inspector_name": "John Doe",
  "date": new Date().toISOString()
});

External systems integration

You can integrate the Field App with other applications using webhooks.

Webhooks for real-time integration

Configure webhooks to receive notifications when surveys are submitted through the Field App. Webhooks are configured through the ArcGIS Feature Layer's webhook management:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Configure webhook using ArcGIS REST API
const featureLayerUrl = "https://services.arcgis.com/your_org/arcgis/rest/services/your_survey/FeatureServer/0";
const webhookPayload = {
  name: "Survey123 Submission Webhook",
  hookUrl: "https://your-system.com/webhook/survey123",
  changeTypes: "INSERT,UPDATE,DELETE",
  signatureKey: "your-signature-key",
  active: true,
  f: "json",
  token: "YOUR_ACCESS_TOKEN"
};

// POST to create webhook
fetch(`${featureLayerUrl}/createWebhook`, {
  method: "POST",
  headers: {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  body: new URLSearchParams(webhookPayload)
})
.then(response => response.json())
.then(result => {
  console.log("Webhook created:", result);
})
.catch(error => {
  console.error("Error creating webhook:", error);
});

You can process incoming webhook from Survey123 using the ArcGIS REST API. Below is an example of how to process incoming webhook from Survey123.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Process incoming webhook from Survey123
app.post('/webhook/survey123', function(req, res) {
  var eventType = req.body.eventType;
  var surveyInfo = req.body.surveyInfo;
  var feature = req.body.feature;
  var userInfo = req.body.userInfo;

  if (eventType === 'addData') {
    // Process new survey submission from Field App
    processNewSubmission(feature.attributes);

    // Example: Create workflow task
    createWorkflowTask(feature.attributes);

    // Example: Send notification
    sendNotification(surveyInfo.name, userInfo.username);
  }

  res.status(200).send('OK');
});

Data export and integration

Export survey data collected by the Field App for integration with external systems:

FormatUse CaseAccess Method
CSVSpreadsheet analysis, data importFeature Layer REST API with f=csv
JSONWeb application integrationFeature Layer REST API with f=json
GeoJSONGIS platform integrationFeature Layer REST API with f=geojson
PDF ReportsDocument generationSurvey123 REST API report endpoint

You can use the ArcGIS API for Python to export survey data for integration with external systems. Below is an example of how to export survey data for integration with external systems.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# Export survey data from Field App
import requests
import pandas as pd
import json

def exportSurveyData(featureLayerUrl, token, outputFormat='json'):
    """
    Export survey data from ArcGIS Survey123 Field App

    Args:
        featureLayerUrl: URL of the feature layer containing survey data
        token: Authentication token
        outputFormat: Export format ('json', 'csv', 'geojson')

    Returns:
        Exported data or None if error occurs
    """
    try:
        # Query survey data
        url = f"{featureLayerUrl}/query"
        params = {
            'where': '1=1',
            'outFields': '*',
            'returnGeometry': True,
            'f': 'json',
            'token': token
        }

        response = requests.get(url, params=params)
        response.raise_for_status()
        data = response.json()

        if 'error' in data:
            print(f"Error querying data: {data['error']}")
            return None

        # Process based on output format
        if outputFormat == 'csv':
            # Convert to CSV using pandas
            features = data.get('features', [])
            if features:
                df = pd.DataFrame([f['attributes'] for f in features])
                df.to_csv('survey_export.csv', index=False)
                print(f"Exported {len(features)} records to survey_export.csv")
                return df

        elif outputFormat == 'geojson':
            # Convert to GeoJSON
            geojson = {
                'type': 'FeatureCollection',
                'features': []
            }
            for feature in data.get('features', []):
                geojson['features'].append({
                    'type': 'Feature',
                    'properties': feature['attributes'],
                    'geometry': feature.get('geometry')
                })

            with open('survey_export.geojson', 'w') as f:
                json.dump(geojson, f)
            print(f"Exported {len(geojson['features'])} records to survey_export.geojson")
            return geojson

        else:  # JSON format
            with open('survey_export.json', 'w') as f:
                json.dump(data, f, indent=2)
            print(f"Exported {len(data.get('features', []))} records to survey_export.json")
            return data

    except requests.exceptions.RequestException as e:
        print(f"Network error: {str(e)}")
        return None
    except Exception as e:
        print(f"Error exporting survey data: {str(e)}")
        return None

# Example usage
if __name__ == "__main__":
    feature_layer_url = "https://services.arcgis.com/your_org/arcgis/rest/services/your_survey/FeatureServer/0"
    access_token = "YOUR_ACCESS_TOKEN"

    # Export as CSV
    exportSurveyData(feature_layer_url, access_token, 'csv')

    # Export as GeoJSON
    exportSurveyData(feature_layer_url, access_token, 'geojson')

Best practices

Follow these essential best practices for extending and integrating the Survey123 Field App:

  • Design for offline-first: Optimize surveys and integrations for offline data collection scenarios
  • Use appropriate integration methods: Choose the right approach (URL schemes, webhooks, REST API) for your use case
  • Handle authentication properly: Implement secure authentication for external system integrations
  • Test on mobile devices: Verify integrations work correctly on actual mobile devices and networks
  • Monitor performance: Track data synchronization and app performance in field conditions

Code examples

Manage your surveys programmatically

Developers can manage surveys and data collection programmatically using the ArcGIS API for Python:

ArcGIS Maps SDK for JavaScriptArcGIS Maps SDK for JavaScriptArcGIS API for Python
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Access Survey123 data via REST API
const surveyUrl = "https://survey123.arcgis.com/api/surveys/your_survey_id";
const token = "YOUR_ACCESS_TOKEN";

// Get survey metadata
fetch(surveyUrl + "?token=" + token)
  .then(response => response.json())
  .then(survey => {
    console.log("Survey title:", survey.title);
    console.log("Feature layer:", survey.featureLayerUrl);
  });

// Query survey responses
const featureLayerUrl = "https://services.arcgis.com/your_org/arcgis/rest/services/your_survey/FeatureServer/0";
const queryUrl = featureLayerUrl + "/query?where=1=1&outFields=*&f=json&token=" + token;

fetch(queryUrl)
  .then(response => response.json())
  .then(data => {
    console.log("Survey responses:", data.features);
  });

Integrate with other applications

Integrate the Field App with other applications using URL schemes:

ArcGIS Maps SDK for JavaScriptArcGIS Maps SDK for JavaScriptArcGIS Maps SDK for Swift
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// Launch Survey123 Field App with URL scheme integration
function launchSurveyApp(surveyId, prefillData, useCustomScheme) {
  var baseUrl = useCustomScheme ? "arcgis-survey123://" : "https://survey123.arcgis.app";
  var params = new URLSearchParams({
      itemID: surveyId
  });

  // Add callback URL (use 'callback' for app link, 'returnURL' for custom scheme)
  if (useCustomScheme) {
      params.append("returnURL", window.location.href);
  } else {
      params.append("callback", encodeURIComponent(window.location.href));
  }

  // Add prefill data
  if (prefillData) {
      for (var key in prefillData) {
          params.append(key, prefillData[key]);
      }
  }

  var surveyUrl = baseUrl + "?" + params.toString();

  // Try to open the survey
  window.location.href = surveyUrl;

  // Fallback to app store if app not installed (mobile only)
  setTimeout(function() {
      if (document.hidden) {
          // App opened successfully
          console.log("Survey app launched");
      } else {
          // Detect platform and redirect to appropriate store
          var userAgent = navigator.userAgent || navigator.vendor || window.opera;
          if (/android/i.test(userAgent)) {
              window.location.href = "https://play.google.com/store/apps/details?id=com.esri.survey123";
          } else if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
              window.location.href = "https://apps.apple.com/app/arcgis-survey123/id993015031";
          }
      }
  }, 1500);
}

// Example usage with app link (recommended)
launchSurveyApp("abc123def456", {
  "inspector_name": "John Doe",
  "location": "Building A"
}, false);

// Example usage with custom scheme (alternative)
launchSurveyApp("abc123def456", {
  "inspector_name": "Jane Smith",
  "site_id": "SITE-001"
}, true);

Configure offline capabilities

Programmatically configure offline capabilities for field deployment:

ArcGIS API for PythonArcGIS API for PythonArcGIS Maps SDK for JavaScript
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from arcgis.gis import GIS
from arcgis.features import FeatureLayer
import requests

# Configure offline survey deployment
def configureOfflineSurvey(feature_layer_url, username, password):
    # Connect to ArcGIS Online
    gis = GIS("https://www.arcgis.com", username, password)

    # Get the feature layer
    feature_layer = FeatureLayer(feature_layer_url, gis=gis)

    # Configure offline settings for the feature layer
    offline_config = {
        "supportsOffline": True,
        "maxRecordCount": 1000,
        "syncEnabled": True,
        "syncCapabilities": {
            "supportsAsync": True,
            "supportsRegisteringExistingData": True,
            "supportsSyncDirectionControl": True,
            "supportsPerLayerSync": True,
            "supportsPerReplicaSync": False,
            "supportsRollbackOnFailure": False,
            "supportsAttachmentsSyncDirection": True
        }
    }

    # Update the feature layer definition
    update_result = feature_layer.manager.update_definition(offline_config)

    if update_result['success']:
        print("Offline configuration updated successfully")
        return feature_layer
    else:
        raise Exception("Failed to update offline configuration")

# Create offline replica for survey data
def createOfflineReplica(feature_layer_url, extent, username, password):
    gis = GIS("https://www.arcgis.com", username, password)
    feature_layer = FeatureLayer(feature_layer_url, gis=gis)

    # Create replica parameters
    replica_params = {
        "replicaName": f"SurveyOffline_{int(time.time())}",
        "layers": "0",
        "geometry": extent,
        "geometryType": "esriGeometryEnvelope",
        "inSR": "4326",
        "outSR": "4326",
        "transportType": "esriTransportTypeUrl",
        "returnAttachments": True,
        "returnAttachmentsDataByUrl": False,
        "async": False,
        "syncModel": "none",
        "dataFormat": "filegdb"
    }

    # Create the replica
    replica_result = feature_layer.replicas.create(replica_params)

    if replica_result['success']:
        print(f"Offline replica created: {replica_result['replicaUrl']}")
        return replica_result
    else:
        raise Exception("Failed to create offline replica")

# Usage example
import time

# Configure offline capabilities
feature_layer_url = "https://services.arcgis.com/your-org/arcgis/rest/services/YourSurvey/FeatureServer/0"
extent = {
    "xmin": -122.5,
    "ymin": 37.7,
    "xmax": -122.3,
    "ymax": 37.8,
    "spatialReference": {"wkid": 4326}
}

try:
    # Configure offline settings
    layer = configureOfflineSurvey(feature_layer_url, "username", "password")

    # Create offline replica
    replica = createOfflineReplica(feature_layer_url, extent, "username", "password")

except Exception as e:
    print(f"Error: {e}")

Tutorials

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.