Implementing a Capacitor Plugin
Capacitor plugins provide a practical approach to structured communication through a Portal. The Capacitor bridge is used under the hood in Portals, allowing Capacitor plugins to be used.
In this step, you will author a Capacitor plugin to log analytics.
Ensure you are serving the Expenses web app using the Portals CLI before proceeding.
Exploring the problem
Business sponsors of the Expenses web app would like to introduce analytics, with the following requirements:
- The ability to log navigation to a new screen shall exist.
- The ability to log specific actions taken in the app shall exist.
- Every analytic entry shall track the platform the log occurred on.
- Analytics shall be logged when the web app is accessed through mobile or on the web.
Based on the requirements, the same actions must be available whether the Expenses web app is presented through a Portal or accessed on a web browser, but the implementation of the actions differ based on platform.
Authoring a Capacitor plugin is ideal in this case. The functionality of a Capacitor plugin is specified by a TypeScript API. Android, iOS, and web developers create platform-specific implementations that adhere to the defined API. During runtime, a Capacitor plugin dynamically directs calls to the appropriate implementation.
Capacitor plugins perform platform-detection under the hood, making them a good abstraction for processes that require different implementations on different platforms.
Defining the API contract
Based on the requirements above, the following interface is reasonable for the analytics plugin:
_10interface AnalyticsPlugin {_10 logAction(opts: { action: string, params?: any }): Promise<void>;_10 logScreen(opts: { screen: string, params?: any }): Promise<void>;_10}
Notice that the interface doesn't address the requirement of tracking the running platform. This is an implementation detail that can be addressed when platform-specific code is written.
Create a new file, web/shared/portals/analytics-plugin.ts
and populate the file with the interface above.
Registering the plugin
The Capacitor plugin API is available as part of the @capacitor/core
npm package. For the purpose of this training, it will be added as a dependency of the web package containing the project's shared Portals code:
Use @capacitor/core
to register the plugin with the Expenses web app:
Register the analytics plugin using the registerPlugin()
method.
The string "Analytics"
sets the plugin name, and it must be consistent across different platform implementations.
Replace the existing implementation in web/shared/portals/index.ts
and point to the new implementation.
Register the analytics plugin using the registerPlugin()
method.
The string "Analytics"
sets the plugin name, and it must be consistent across different platform implementations.
Replace the existing implementation in web/shared/portals/index.ts
and point to the new implementation.
Save the code, then tap either the plus icon or an individual expense's edit (pencil) icon. If you were to monitor network traffic (optional), you would notice requests sent to an analytics endpoint. These requests contain data about the event, including a property platform
indicating the running platform. For this demo, the analytics plugin has been implemented in the native binary running on your device or simulator.
Everything works when the plugin runs on a mobile platform, but if you navigate to http://localhost:5173
you will encounter the following error:
_10"Analytics" plugin is not implemented on web
As a web developer, your responsibility is to author the web implementation of a Capacitor plugin. In the following section, you will write the web implementation of the analytics plugin to meet the requirements outlined at the beginning of this step.
Web implementation
The Expenses web app needs to record analytic events whether it is being presented through a Portal, or running as a standalone application on the web.
To that end, the analytics Capacitor plugin must contain an implementation when it is used on the web. You can write the web implementation for a Capacitor plugin by writing a class that extends WebPlugin
and providing an instance of the class as part of registerPlugin()
:
Add a class that extends WebPlugin
and implements AnalyticsPlugin
in web/shared/portals/analytics-plugin.ts
.
Register an instance of this class for the web implementation as part of the registerPlugin()
call.
Use utility methods available as part of the local @jobsync/api
package to make calls to the analytics backend.
Note that platform: 'web'
is being added to the event payload.
Add a class that extends WebPlugin
and implements AnalyticsPlugin
in web/shared/portals/analytics-plugin.ts
.
Register an instance of this class for the web implementation as part of the registerPlugin()
call.
Use utility methods available as part of the local @jobsync/api
package to make calls to the analytics backend.
Note that platform: 'web'
is being added to the event payload.
Return to the browser and notice that no more errors remain. If you monitor network traffic (optional), you will notice network requests made to an analytics endpoint with a data payload containing platform: 'web'
, confirming that the web implementation is in use. The analytics plugin determined that the Expenses web app is running on a web platform, and picked the appropriate plugin implementation to use.
Detailed information about Capacitor plugins and the Capacitor Plugin API can be found here.
Conclusion
With the completion of the analytics Capacitor plugin, the Expenses web app is ready to be bundled within the Jobsync superapp! In this training module, you exercised the various ways web apps can communicate through a Portal. Furthermore, you used the Portals CLI to set up a development workflow to test and debug a web app running within the Portal the mobile application will present it in.
You now have the tools in place to take any web app and make it Portals-ready. Happy coding!! 🤓