i set up Google Analytics for my iOS-App and it is basically working fine (Screen Tracking, Purchases,...), except the install Campaign tracking is not ok.
I saw a similar question here which is not solved: 
[Google analytics iOS campaign tracking testing on development](https://stackoverflow.com/questions/28428224/google-analytics-ios-campaign-tracking-testing-on-development)

This is the guide i used to implement (is in Objective-C):
<https://developers.google.com/analytics/devguides/collection/ios/v3/campaigns#general-campaigns>

I see in my Google Analytics Dashboard the referrer installs, but no campaign installs.

This is a test Url

[https://click.google-analytics.com/redirect?tid=UA-51157298-2&url=https%3A%2F%2Fitunes.apple.com%2Fat%2Fapp%2Fbikersos-motorrad-unfall-sos%2Fid980886530&aid=com.BikerApps.BikerSOS&idfa=%{idfa}&cs=test\_source&cm=test\_medium&cn=test\_campaign&cc=test\_campaign\_content&ck=test\_term](https://click.google-analytics.com/redirect?tid=UA-51157298-2&url=https%3A%2F%2Fitunes.apple.com%2Fat%2Fapp%2Fbikersos-motorrad-unfall-sos%2Fid980886530&aid=com.BikerApps.BikerSOS&idfa=%25%7Bidfa%7D&cs=test_source&cm=test_medium&cn=test_campaign&cc=test_campaign_content&ck=test_term)

which i generated here: 
<https://developers.google.com/analytics/devguides/collection/ios/v3/campaigns#url-builder>

My Code which should track the install is the following:

AppDelegate:

```
//Method where app parses any URL parameters used in the launch
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {

    //Track google Analytics URL
    GAService.shared.trackURL(url)

    //some other handlers here ....
    return true/false
}

```

GAService Singleton:

```
@objc public class GAService : NSObject {
private let trackID : String = "UA-xxxxxx-x"

var trackGoogleAnalytics : Bool = Constants.Analytics.trackGoogleAnalytics
private let UTM_SOURCE_KEY : String = "xxx"
private let UTM_MEDIUM_KEY : String = "xxx"
private let UTM_CAMPAIGN_KEY : String = "xxx"
var trackUncaughtExceptions : Bool = true
var tracker : GAITracker? = nil

static let shared = GAService()

var UtmSource : String {
    get {
        if let utm = UserDefaults.standard.string(forKey: UTM_SOURCE_KEY) {
            return utm
        }
        return ""
    }
    set {
        if UserDefaults.standard.string(forKey: UTM_SOURCE_KEY) == nil {
            UserDefaults.standard.set(newValue, forKey: UTM_SOURCE_KEY)
            UserDefaults.standard.synchronize()
        }
    }
}
var UtmCampaign : String {
    get {
        if let utm = UserDefaults.standard.string(forKey: UTM_CAMPAIGN_KEY) {
            return utm
        }
        return ""
    }
    set {
        if UserDefaults.standard.string(forKey: UTM_CAMPAIGN_KEY) == nil {
            UserDefaults.standard.set(newValue, forKey: UTM_CAMPAIGN_KEY)
            UserDefaults.standard.synchronize()
        }
    }
}
var UtmMedium : String {
    get {
        if let utm = UserDefaults.standard.string(forKey: UTM_MEDIUM_KEY) {
            return utm
        }
        return ""
    }
    set {
        if UserDefaults.standard.string(forKey: UTM_MEDIUM_KEY) == nil {
            UserDefaults.standard.set(newValue, forKey: UTM_MEDIUM_KEY)
            UserDefaults.standard.synchronize()
        }
    }
}
private override init() {
    super.init()

    if(trackGoogleAnalytics) {
        tracker = GAI.sharedInstance().tracker(withTrackingId: trackID)
        tracker!.allowIDFACollection = true

        GAI.sharedInstance().trackUncaughtExceptions = trackUncaughtExceptions
        GAI.sharedInstance().logger.logLevel = GAILogLevel.error
        GAI.sharedInstance().dispatchInterval = 1
    }
}

public func trackURL(_ url : URL){
    let urlString = url.absoluteString
    // setCampaignParametersFromUrl: parses Google Analytics campaign ("UTM")
    // parameters from a string url into a Map that can be set on a Tracker.
    let hitParams : GAIDictionaryBuilder = GAIDictionaryBuilder()

    // Set campaign data on the map, not the tracker directly because it only
    // needs to be sent once.
    hitParams.setCampaignParametersFromUrl(urlString)

    // Campaign source is the only required campaign field. If previous call
    // did not set a campaign source, use the hostname as a referrer instead.
    if((hitParams.get(kGAICampaignSource) != nil) && (url.host ?? "").length() != 0) {
        hitParams.set("referrer", forKey: kGAICampaignMedium)
        hitParams.set(url.host, forKey: kGAICampaignSource)
    }
    let hitParamsDict : [AnyHashable : Any] =  hitParams.build() as Dictionary as [AnyHashable : Any]

    if(hitParamsDict.count > 0) {
        // A screen name is required for a screen view.
        let source : String? = hitParams.get(kGAICampaignSource)
        let medium : String? = hitParams.get(kGAICampaignMedium)
        let campaign : String? =  hitParams.get(kGAICampaignName)
        if(source != nil || medium != nil || campaign != nil) {
            tracker?.set(kGAIScreenName, value: "openUrl")
            GAService.shared.UtmSource = source ?? ""
            GAService.shared.UtmMedium = medium ?? ""
            GAService.shared.UtmCampaign = campaign ?? ""
        }

        // SDK Version 3.08 and up.
        //[tracker send:[[[GAIDictionaryBuilder createScreenView] setAll:hitParamsDict] build]];
        let sendDict : [AnyHashable : Any] =  GAIDictionaryBuilder.createScreenView().setAll(hitParamsDict).build() as Dictionary as [AnyHashable : Any]
        tracker?.send(sendDict)
        tracker?.set(kGAIScreenName, value: nil)
    }
}

```

As i have to set a screenName for such a tracking i defined openUrl as a constant and set it to nil afterwards i sent the dictionary.

I hope anybody can see what i'm doing wrong

thank you in advance