How can development and support teams work together on bugs?

February 26, 2021
Published
10 minutes
Reading time
Team Culture
Category

Often enough things work just fine until that one support ticket gets escalated to a bug report. We’ve all been there, quietly sobbing as the report comes in a complete mess and quite impossible to understand. These aren’t fun for either side, as stress points arise when trying to debug it.

To be honest, your average customer support agent is no developer either. In most cases, he’s just trying to do his very best to cover the basics. Such a process can be exhausting, and may even cause a certain amount of backlash from the user. Can one save both valuable time and deliver world-class bug reports along the way? Read on and find out.

Filling in the gap between bug reports and support tickets

There’s certain disarray when it comes to the way bugs and tickets are handled. Most tickets get stored in helpdesk software, while developers use bug trackers to store information about any known issues. These two separate systems, and while they work apart — they don’t exactly work well together. This creates a gap that needs to be filled if you want to have an efficient debugging system in place.

Comparison between bug tracking and helpdesk software

Can a customer support agent really help users deliver world-class bug reports? Yes, with a little assistance from a developer. Almost every app out there uses a reporting tool that allows them to report and log bugs, so let’s use that to our advantage and to fill in the gap.

Working together instead of working apart

Customer support and developers might not mix by default, but they are both tied to the same group of people – the users. Its user satisfaction with the service that inspires these two groups of people to work together, not apart. Let us explore just how they can do so.

The perfect weapon for customer support teams. Deep links are clickable links, that once triggered can open an app and perform a specified action(s) inside it, like submit a bug report from the background. All the user needs is to open the link, and a bug report is sent to the developers’ dashboard.

Deep links open up a world of possibilities when it comes to how tickets get handled, empowering support teams to easily escalate issues to bugs with a single deep link.

Furthermore, deep-link bug reports carry the potential to cut down on countless hours spent chatting with users by removing the need to manually write bug reports. All available bug data arrives out-of-the-box, allowing customer support teams to focus on other tickets and developers to debug more effectively.

How are they created? To get started, you’ll need a little developer’s help. The easiest way to create a deep link is trough the Firebase console, as shown below.

Creating a deep link using the Firebase console

After that, it’s all about setting up an app to receive them and handle them effectively. We’ll talk more about setting up deep links on iOS and Android in the next chapter.

It’s time to take a closer look at deep links from a developer perspective and explore how to set them up in order to receive world-class bug reports from users.

Deep links are dynamic and work across multiple platforms: iOS, Android and Web. This offers maximum flexibility when it comes to set up and experience. What does that mean, exactly?

Let’s say a user was to open a deep link on its phone, it would lead them straight into your app. However, opening the same link on a desktop computer will lead them to content on your webpage. That’s the magic of deep links.

Once you’ve created a deep link using one of the methods offered by Firebase, it’s time to set up your app to receive them. Here’s a checklist of all the things you’ll need to do before you can get started:

  • Add Firebase to your Android project
  • Make sure to include Google’s Maven repository in both your buildscript and allprojects sections
  • Add the dependency for the Dynamic Links Android library to your module (app-level) Gradle file

After that’s done, it’s time to add an intent filter that catches deep links of your domain. This is also required in order to receive link data after the app has been installed or updated from the Play Store. Here’s what you need to add to your AndroidManifest.xml file:

1 <intent-filter> 
2   <action android:name="android.intent.action.VIEW"/> 
3   <category android:name="android.intent.category.DEFAULT"/> 
4   <category android:name="android.intent.category.BROWSABLE"/> 
5   <data
6    android:host="example.com"
7    android:scheme="https"/> 
8 </intent-filter>

Once the link is clicked it will be handled by an app according to the intent filter.

Next up, let’s define how to actually receive & handle deep link by calling the getDynamicLink() method. Let’s explore an example of a deep link with silent reporting implemented:

1 FirebaseDynamicLinks.getInstance() 
2    .getDynamicLink(getIntent()) 
3    .addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() { 
4      @Override 
5      public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) { 
6        // Get deep link from result (may be null if no link is found) 
7        Uri deepLink = null; 
8        if (pendingDynamicLinkData != null) { 
9        deepLink = pendingDynamicLinkData.getLink(); 
10       } 
11       // Handle the deep link. For example, open the linked 
12       // content, or apply promotional credit to the user's 
13       // account. 
14       // ... 
15       Shake.silentReport("deeplinkReport", new EmptyShakeReportData(), new ShakeReportConfiguration()); 
16       // ... 
17      } 
18    }) 
19    .addOnFailureListener(this, new OnFailureListener() { 
20      @Override 
21      public void onFailure(@NonNull Exception e) { 
22      Log.w(TAG, "getDynamicLink:onFailure", e); 
23      } 
24    });:

Notice the Shake.silentReport method, as developed by Shake. It invokes the SDK once the link is open and submits a bug report without showing any UI.

The data you receive as part of the report depends on the configuration you set up. It includes Essentials, optionally passing: Activity history, Black box, Metadata, and Attachments. You’ll also want to call getDynamicLink() in every activity that might be launched by the link, in order to clearly retrieve the link and so the data is processed only once.

To receive the deep links that you created, include the Firebase Dynamic Links SDK in your app and call the FirebaseDynamicLinks.getDynamicLink() method when your app loads.

Deep links work also great on iOS using Firebase and require iOS 8 or newer. Here’s a list of things you need to set up in order for your app to start receiving them:

  • Add Firebase to your iOS project
  • Run pod install and open the created .xcworkspace file
  • Ensure that your app’s App Store ID and your App ID prefix is specified in your app’s settings

Next, let’s see how to open set up to your app to receive and open a deep link.

To begin, create a new URL type that can be for Dynamic Links. Set its Identifier field to a unique value of your choosing and the URL scheme field to match your bundle identifier. This will act as the default scheme used by deep links. Next, navigate to the Capabilities tab and enable Associated Domains and add the following value to the list:

1 applinks:your_dynamic_links_domain

You’ll also need to import the Firebase module into UIApplicationDelegate. After that, configure a FirebaseApp shared instance in the apps application :didFinishLaunchingWithOptions: method:

1 // Use Firebase library to configure APIs 
2 FirebaseApp.configure()

Let us also handle links received as Universal Links when the app is already installed. This can be done in the application:continueUserActivity:restorationHandler: method, as shown below.

1 func application(_ application: UIApplication, continue userActivity: NSUserActivity, 
2                 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { 
3    let handled = DynamicLinks.dynamicLinks().handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in 
4    // ... 
5    } 
6 return handled 
8 }

It’s time to handle all the links received through your app custom URL scheme and define the details of silent reports that are submitted once your app receives a link and is opened on an iOS device. Here’s an example of how this would look like in code:

1 @available(iOS 9.0, *) 
2 func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool { 
3    return application(app, open: url, 
4                       sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String, 
5                       annotation: "") 
6 } 
7 func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { 
8    if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) { 
9      // Handle the deep link. For example, show the deep-linked content or 
10     // apply a promotional offer to the user's account. 
11     // ... 
12    let reportData = ShakeReportData(bugDescription: "#dynamicLink", attachedFiles: [])
13
14.   let reportConfiguration = ShakeReportConfiguration()
15    reportConfiguration.includesScreenshotImage = true
16    reportConfiguration.includesBlackBoxData = true
17    reportConfiguration.includesActivityHistoryData = true
18
19.   Shake.silentReport(reportData: reportData, reportConfiguration: reportConfiguration)
20    return true 
21    } 
22    return false 
23 }

Notice how the SHK.silentReport passes on a configuration that can be defined according to preference. In the case above, the following will be included in the bug report:  Attachments, Black boxActivity history, and a Screenshot.

If a matching link isn’t found in the app the FIRDynamicLink URL will be set to nil, indicating that a match hasn’t been found for the pending deep link.

To receive the deep links that you created, you have to include the Firebase Dynamic Links SDK in your app and call the handleUniversalLink: and dynamicLinkFromCustomSchemeURL: methods when it loads.

Let’s explore some of the upsides deep links can bring to customer support teams below.

  • Speedy responses and faster issue handling. Responding to issues faster lets you build consistency and trust among users.
  • More accountability and follow-through. Having a bulletproof bug reporting process in place and taking ownership of eventual shortcomings inspires user confidence in the service provided.
  • A sense of security and understanding. Knowing how to effectively troubleshoot an issue provides users with a sense of security and understanding that it will be dealt with effectively.

Let us take a look at what development teams have to gain from using deep links.

  • Actionable bug reports. Each bug report is pre-packed with over 1000 usable data points.
  • Faster bug resolution time. Debug faster with all the data provided to you out-of-the-box.
  • All reports organized in one place. All the reports you receive are organized in a list and can be accessed from one dashboard.

Conclusion

Development and customer support teams can work well together if given the chance and create a bug reporting process that will benefit both sides. All it takes is the time to set-up and patience to execute such a feat on an everyday scale.

More so, there’s no more need to writing about manual reports ever again. The fact that bug reports via deep links arrive out-of-the-box will come as a nice addition to any customer support teams and their daily workload while giving developers all they need to debug faster.

About Shake

From internal bug reporting to production and customer support, our all-in-one SDK gets you all the right clues to fix issues in your mobile app and website.

We love to think it makes CTOs life easier, QA tester’s reports better and dev’s coding faster. If you agree that user feedback is key – Shake is your door lock.

Read more about us here.

Bug and crash reporting tool you’ve been looking for.

Add to app in minutes

Doesn’t affect app speed

GDPR & CCPA compliant