Title: iOS tracking SDK for mobile apps
Author: staff
Published: August 1, 2022
Last modified: May 21, 2026

---

 1. [Installation resources](https://docs.parse.ly/installation-resources/)
 2. [Add-on Features](https://docs.parse.ly/installation-resources/add-on-features/)
 3. [Mobile app tracking](https://docs.parse.ly/installation-resources/add-on-features/mobile-sdk/)
 4. iOS tracking SDK for mobile apps

#  iOS tracking SDK for mobile apps

The Parse.ly iOS SDK is an iOS framework written in Swift providing Parse.ly tracking
functionality to native iOS apps. Like any other framework you might include in 
your iOS app project, the Parse.ly SDK provides a programming interface usable from
your application code.

The SDK is [open source on GitHub](https://github.com/Parsely/AnalyticsSDK-iOS).

## Integrating with Swift Package Manager

Starting with v0.2.2 the Parse.ly SDK can be integrated using Swift Packet Manager.

To use the SDK in a Swift Package Manager project, add the following line to the
dependencies in your `Package.swift` file:

    ```lang-php
    swift.package(url: "https://github.com/Parsely/AnalyticsSDK-iOS", from: "0.2.2")
    ```

Include “ParselyAnalytics” as a dependency for your target:

    ```lang-php
    swift.target(name: "<target>", dependencies: [
    	.product(name: "ParselyAnalytics", package: "AnalyticsSDK-iOS"),
    ]),
    ```

Below is an example of how you could integrate the SDK with your `Package.swift`
file:

    ```lang-php
       dependencies: [
            .package(url: "https://github.com/Parsely/AnalyticsSDK-iOS", from: "0.2.2"),
        ],
        targets: [
            .target(
                name: "TryParsely",
                dependencies: [
                    .product(name: "ParselyAnalytics", package: "AnalyticsSDK-iOS")
                ]
            ),
        ]
    ```

## Integrating with CocoaPods

The Parsely Analytics SDK is available via [Cocoapods](https://cocoapods.org/pods/ParselyAnalytics).
To start using the Parse.ly iOS SDK in your XCode iOS project, follow these steps:

 * Add a line referencing the SDK to your project’s Podfile: `pod 'ParselyAnalytics','
   ~> 0.0.1'`
 * Replace the version specifier in this Podfile line with the version of the “latest
   release” from [this listing](https://github.com/Parsely/AnalyticsSDK-iOS/releases)
 * Run `pod install` from your project directory to install the SDK and its dependencies

## Using the tracker

At app startup, configure the `Parsely` singleton. A good place to do this might
be the top-level application delegate.

    ```lang-php
    import ParselyAnalytics
    // parsely should be a class attribute of AppDelegate
    var parsely: Parsely!
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
      self.parsely = Parsely.sharedInstance
      self.parsely.configure(siteId: "<PARSELY_SITE_ID>")
      // other app initialization...
      return true
    }
    ```

Replace `<PARSELY_SITE_ID>` with your Parse.ly site ID. Often, this will be the 
domain name of your website.

Once you’ve done this, you can call tracking methods on `self.parsely`. Here are
some examples:

    ```lang-php
    self.parsely.trackPageView(url: "http://mysite.com/story1")
    self.parsely.startEngagement(url: "http://mysite.com/story2")
    self.parsely.stopEngagement()
    ```

## Providing metadata

Pageview metadata is only required for URLs not accessible over the internet (i.
e. app-only content) or if you are using an “in-pixel” integration. Otherwise, metadata
will be gathered by Parse.ly’s crawling infrastructure.

**Note**

For the metadata integration types below, it is possible to send a canonical URL
that does not need to resolve to an extant page when navigated to in a browser.

If you do this, it is important that the canonical URL provided for the mobile post
should still be a URL with the domain matching a domain from which other traffic
is sent for the Site ID. The URL should also be unique to the post among all posts
for the Site ID.

There are two methods for providing Parse.ly with metadata for content that’s only
accessible via the Mobile SDK:

 1. Primary recommendation: updating metadata using the [metadata API endpoint](https://docs.parse.ly/api-metadata-endpoint/).
 2. Back-up option: Sending metadata “in-pixel” with every event sent with the Mobile
    SDK. This should be used only in special cases. For example, this is an appropriate
    method for a mobile-app only company.

**Note**

You should only use the “in-pixel” method if **all **of the content on your app 
is app-only.

## Metadata objects

Some methods in the SDK’s API accept `ParselyMetadata` objects as arguments. These
objects are used to represent metadata for the content being tracked and conform
to a similar standard to the [Parsely metadata tag](https://docs.parse.ly/metadata/).

You can create a `ParselyMetadata` object to pass to a tracking function by calling
the class’ constructor:

    ```lang-php
    let metadata = ParselyMetadata(authors: ["Jane Doe"], section: "myvertical")
    self.parsely.trackPageView("http://mysite.com/story1", metadata: metadata)
    ```

## API Documentation

### Parsely.configure()

Configure the Parsely tracking SDK for this particular run of the application. Should
be called once per application load, before other Parsely SDK functions are called.

| Parameter | Type | Required | Description | 
| siteId | String | yes | The Parsely site ID for which the pageview event should be counted. Can be overridden on individual tracking method calls. | 
| handleLifecycle | Bool | no | If true, set up listeners to handle tracking across application lifecycle events. Defaults to true. |

### ParselyMetadata()

NOTE: This metadata class is functionally limited. It does not contain all metadata
values. Only use this class to provide metadata if you are choosing to _not_ use
the recommended method above.

This is a class used to manage and reuse metadata conforming to Parsely’s schema.
Pageview metadata is only required for URLs not accessible over the internet (i.
e. app-only content) or if you are using an “in-pixel” integration. Otherwise, metadata
will be gathered by Parse.ly’s crawling infrastructure.

| Parameter | Type | Required | Description | 
| canonical_url | String? | no | A post’s [Parse.ly canonical URL](https://docs.parse.ly/the-parsely-canonical-url/). For videos, overridden with the `videoID` method argument and thus can be omitted | 
| pub_date | Date? | no | The date this piece of content was published | 
| title | String? | no | The title of the content | 
| authors | Array? | no | The names of the authors of the content. Up to 10 authors are accepted | 
| image_url | String? | no | URL at which the main image for this content is located | 
| section | String? | no | The category or vertical to which this content belongs | 
| tags | Array? | no | User-defined tags for the content. Up to 20 are allowed | 
| duration | TimeInterval? | no | The duration of the content. For videos, overridden by the `duration` method argument and thus can be omitted |

### Parsely.trackPageView()

Track a pageview event

| Parameter | Type | Required | Description | 
| url | String | yes | The url of the page that was viewed | 
| urlref | String | no | The url of the page that linked to the viewed page. Analogous to HTTP referer | 
| metadata | ParselyMetadata | yes | Metadata for the viewed page ([example](https://docs.parse.ly/parse-ly-video-tracking/-tracking-v2/#h-custom-integration-for-unsupported-video-players)) | 
| extraData | Dictionary<String, Any>? | no | A dictionary of additional information to send with the generated pageview event | 
| siteId | String | no | The Parsely site ID for which the pageview event should be counted |

### Parsely.startEngagement() (heartbeat tracking)

Recommended implementation: Call `startEngagement` when a post is navigated to, 
and to call `stopEngagement` when it’s navigated away from.

Start engaged time tracking for the given URL. Once called, heartbeat events will
automatically be sent periodically to capture engaged time for this url until engaged
time tracking is stopped.

This call also automatically stops tracking engaged time for any urls that are not
the current url.

The value of `url` should be a URL for which `trackPageview` has been called.

| Parameter | Type | Required | Description | 
| url | String | yes | The url of the page being engaged with | 
| urlref | String | no | The url of the page that linked to the page being engaged with. Analogous to HTTP referer | 
| extraData | Dictionary<String, Any>? | no | A dictionary of additional information to send with generated heartbeat events | 
| siteId | String | no | The Parsely site ID for which the heartbeat events should be counted |

### Parsely.stopEngagement()

Stop tracking engaged time for the currently engaged url. This method should be 
called when a user navigates away from a specific page or piece of content, when
the application is backgrounded (using the `applicationDidEnterBackground` callback),
and when the application is forcefully closed (using the `applicationWillResignActive`
callback). Once called, one additional heartbeat event may be sent, after which 
heartbeat events will stop being sent.

### Parsely.trackConversion()

Track a conversion event (e.g. newsletter signup, subscription, purchase, lead capture).
The SDK constructs a `conversion` event with the goal identity carried in `extraData`
and dispatches it through the same flush queue and `mobileproxy` endpoint used by`
trackPageView` — no separate setup or network plumbing required.

Recommended implementation: Call `trackConversion` at the moment a conversion completes—
after a paywall purchase succeeds, a newsletter signup form is submitted, a lead-
capture form is sent, a paid plan is activated, etc. For best attribution results,
call `trackPageView` for the relevant in-app pages before the conversion so the 
conversions topology has session history to attribute against.

| Parameter | Type | Required | Description | 
| url | String | yes | The url at which the conversion occurred | 
| conversionType | ConversionType | yes | The url of the page that linked to the page being engaged with. Analogous to HTTP referer | 
| conversionLabel | String | yes | A customer-defined identifier for this conversion (e.g. `"Homepage CTA"`, `"Annual Subscription"`). Must be non-empty — calls with an empty string are skipped before being enqueued and an error is logged | 
| urlref | String | no | The url of the page that linked to the conversion page. Analogous to HTTP referer | 
| metadata | ParselyMetadata? | no | Metadata for the page on which the conversion occurred | 
| extraData | Dictionary<String, Any>? | no | A dictionary of additional information to send with the event. The reserved keys `_conversion_type` and `_conversion_label` will be overwritten by the typed parameters above | 
| siteId | String | no | The Parse.ly site ID for which the conversion event should be counted |

### Parsely.trackPlay()

Start tracking view time for a given video being viewed at a given url. Sends a 
videostart event for the given url/parse-ly-video-tracking/ combination. Once called,
vheartbeat events will be sent periodically for this url/parse-ly-video-tracking/
combination until video view tracking is stopped. Stops tracking view time for any
url/parse-ly-video-tracking/ combinations currently being tracked for view time.

| Parameter | Type | Required | Description | 
| url | String | yes | The url at which the video is being viewed. Equivalent to the url of the page on which the video is embedded. If the video is not embedded in a page, should contain a well-formatted URL on your domain (e.g. http:///app-videos). This URL doesn’t need to return a 200 status when crawled, but must be well-formatted so Parse.ly systems recognize it as belonging to your site. | 
| urlref | String | no | The url of the page that linked to the page on which the video is being viewed. Analogous to HTTP referer | 
| vId | String | yes | Unique identifier for the video (videoID). Functions similarly to the [Parse.ly Canonical URL](https://docs.parse.ly/the-parsely-canonical-url/) that Posts use.
It appears as the `"link"` value in the [video network call’s](https://docs.parse.ly/test-integration/#h-review-the-videostart) metadata. Additionally, this value should match the `“link”` passed for the video in the web channel. | 
| duration | TimeInterval | yes | The duration of the video | 
| metadata | ParselyMetadata? | no | Metadata for the video being viewed | 
| extraData | Dictionary<String, Any>? | no | A dictionary of additional information to send with generated vheartbeat events | 
| siteId | String | no | Unique identifier for the video (videoID). Functions similarly to the [Parse.ly Canonical URL](https://docs.parse.ly/the-parsely-canonical-url/) that Posts use.It appears as the `"link"` value in the [video network call’s](https://docs.parse.ly/test-integration/#h-review-the-videostart) metadata. Additionally, this value should match the `“link”` passed for the video on the web channel. |

### Parsely.trackPause()

Stop tracking video view time for the currently viewing url/parse-ly-video-tracking/
combination. Once called, one additional vheartbeat event may be sent per previously-
viewed url/parse-ly-video-tracking/ combination, after which vheartbeat events will
stop being sent.

### Parsely.resetVideo()

Unset tracking data for the given url/parse-ly-video-tracking/ combination. The 
next time `trackPlay` is called for that combination, it will behave as if it had
never been tracked before during this run of the app. This differs from `trackPause`
in that it unlocks `videostart` events, where that function does not.

| Parameter | Type | Required | Description | 
| url | String | yes | The url at which the video was being viewed. Equivalent to the url of the page on which the video is embedded | 
| vId | String | yes | The video ID string for the video being reset |

## Configuring Audience Segments

If your contract includes [Audience Segments](https://docs.parse.ly/installation-developer-resources/add-on-features/setting-up-audience-segments-parsely/),
you can use the extraData parameter in the [page view](https://docs.parse.ly/installation-resources/add-on-features/mobile-sdk/ios-sdk?output_format=md#trackpageview)
and [engagement](https://docs.parse.ly/installation-resources/add-on-features/mobile-sdk/ios-sdk?output_format=md#startengagement)
events.

Pass extraData to set the desired audience(s) in the format of `extraData: ["key":"
value"]`. For example:

    ```lang-js
    Subscribers: extra_data['subscriber'] == 'true'
    Non-subscribers: extra_data['subscriber'] == 'false' 
    ```

To see the full context, review the [sample code on GitHub](https://github.com/Parsely/AnalyticsSDK-iOS/blob/master/Demo/ParselyDemo/FirstViewController.swift#L11).

Last updated: May 21, 2026