Advanced
Theming
The GetintheLoop SDK allows integrations to customize the appearance of managed UIs and provide support for additional languages. The SDK uses a theme object to provide following customizations:
- Spacing
- Colors
- Typography
- Icons
- Other UI-specifics, such as rounded corners, divider size, etc.
Setting a Custom Theme
A custom theme is, at the root, a dictionary of theme values that are applied to the SDK's UI components via NSAppearance
.
Creating and applying a custom theme is straight forward:
- Create a new instance of
LMGTheme
, passing the custom theme properties as a dictionary during instantiation - Apply the theme with the
LMGThemeManager
- Swift
- Objective-C
// Create a new LMGTheme instance
let theme = LMGTheme.init([
"colors": [
"titleText": UIColor.black,
"headlineText": UIColor.black,
"subheadText": UIColor.black,
"bodyText": UIColor.black,
"captionText": UIColor.black,
"overlineText": UIColor.blue,
"primaryAction": [
":normal": UIColor.blue,
],
]
]);
// Set the theme for the SDKs
LMGThemeManager.apply(theme);
// Create a new LMGTheme instance
LMGTheme *theme = [LMGTheme init:@{
@"colors": @{
@"titleText": [UIColor blackColor],
@"headlineText": [UIColor blackColor],
@"subheadText": [UIColor blackColor],
@"bodyText": [UIColor blackColor],
@"captionText": [UIColor blackColor],
@"overlineText": [UIColor blueColor],
@"primaryAction": @{
@":normal": [UIColor blueColor],
},
}
}];
// Set the theme for the SDKs
[LMGThemeManager applyTheme:theme];
Supporting Additional Languages
The GetintheLoop SDKs provide first-party support for English, French, Spanish, and Dutch.
To add support for additional language translations, or to customize the existing translations, an integration can provide a reference to an NSBundle
, via the LMGTheme
instance, that contains the required localization keys.
Notifications & Direct Links
Offers
Sent notification or direct link must have offer id or offer slug available.
Displaying offer details
- Objective-C
@import LMGUI;
...
// Offer Details in no particular Location
UIViewController *offerDetailViewController = [LMGOfferDetailsWireframe viewControllerForOfferId:@"OFFER_ID__OR__SLUG"];
[self.navigationController pushViewController:offerDetailViewController animated:TRUE];
...
// Offer Details in one Location
UIViewController *offerDetailViewController = [LMGOfferDetailsWireframe viewControllerForOfferId:@"OFFER_ID__OR__SLUG" locationId:@"LOCATION_ID__OR__SLUG"];
[self.navigationController pushViewController:offerDetailViewController animated:TRUE];
Business or Location
Sent notification or direct link must have business id, business slug, location slug available.
Displaying business details
The Business Details screen displays the offers and locations available for a business. The locations and offers shown are based on what is available in the current geocontext area.
- Objective-C
@import LMGUI;
...
UIViewController *businessDetailViewController = [LMGBusinessDetailsWireframe viewControllerForBusinessId:@"BUSINESS_ID__OR__SLUG"];
[self.navigationController pushViewController:businessDetailViewController animated:TRUE];
If location services are enabled, the locations displayed will be ordered based on distance from the device.
Displaying location details
- Objective-C
@import LMGUI;
...
UIViewController *locationDetailViewController = [LMGLocationDetailsWireframe viewControllerForBusinessId:@"BUSINESS_ID__OR__SLUG" locationId:@"LOCATION_ID__OR__SLUG"];
[self.navigationController pushViewController:locationDetailViewController animated:TRUE];
Managing Navigation
Once an SDK view is initialized and presented, the SDK manages navigation to other views automatically. In some cases, this navigation behaviour needs to be customized for an integration. For example, if the integration provides custom business listing screens, it may want to override the default behaviour when a Business view is tapped.
The SDK allows an integration to intercept, stop, or otherwise customize internal navigation actions via a Navigation Delegate.
Navigation Delegate
Navigation delegate is an object that implements the LMGClientNavigationDelegate
protocol. LMGClientNavigationDelegate
specifies one method, (UIViewController *)onPendingView:(UIViewController *)pending currentView:(UIViewController *)current data:(NSDictionary *)data
.
This method allows you to inspect the pending ViewController and choose what to present
onPendingView
is called before each navigation action initiated by an SDK managed view. It allows you to customize navigation by returning different values:
- Return the
pending
UIViewController. This is the default navigation behaviour. - Return a custom UIViewController. This will navigate to your custom UIViewController using the standard transition for the current user interaction (most likely a push).
- Return
nil
. This cancels navigation. Can be used to prevent certain views from being shown, or to fully customized the navigation behaviour of a custom UIViewController.
Screen Types
All of the SDK's ViewControllers have a screenType
property that allows you to easily determine the type of screen that is pending navigation. LMGScreenTypes
are:
Collection
OfferDetails
BusinessDetails
LocationDetails
LocationsList
MixedContent
Search
Map
Bookmarks
Rewards
InlineBrowser
EmailClient
Exceptions
While almost all SDK-initiated navigation is customizable via the Navigation Delegate, there are exceptions, primarily the Offer Redemption flow.
Offer Redemption is a complex process that potentially involves a number of different steps and screens. As these are all required to support all the different offer features and use-cases, observing, interrupting, or cancelling these screens via the Navigation Delegate is not permitted.
Example Implementation
Example of implementation onPendingView: currentView: data:
delegate method:
- Swift
- Objective-C
func onPendingView(_ pending: UIViewController, currentView current: UIViewController, data: [AnyHashable : Any]) -> UIViewController? {
if (pending.responds(to: Selector(("screenType")))) {
let screenType = LMGScreenType(rawValue: pending.value(forKey: "screenType") as! UInt)
switch screenType! {
case LMGScreenType.LocationDetails:
// Prevent from any navigation when Location Details screen should be shown
return nil;
case LMGScreenType.Collection:
// Showing YourCustomViewController when Collection screen should be shown
return YourCustomViewController();
default:
// No changes for other screen types
return pending;
}
}
return pending;
}
- (UIViewController *)onPendingView:(UIViewController *)pending currentView:(UIViewController *)current data:(NSDictionary *)data {
if([pending respondsToSelector:@selector(screenType)]) {
// Getting screen type
LMGScreenType type = (LMGScreenType) [[pending valueForKey:@"screenType"] integerValue];
switch (type) {
case LocationDetails:
// Prevent from any navigation when Location Details screen should be shown
return nil;
case Collection:
// Showing YourCustomViewController when Collection screen should be shown
return [YourCustomViewController new];
default:
// No changes for other screen types
return pending;
}
}
return pending;
}
SDK Configuration Options
SDK has some configurations that are optional for the integration:
- Ability to save offers when user is identified (true/false or "VerifiedOnly")
- Ability to share offers and businesses
- Ability to add an attribution badge
- Ability to enable/disable feedback links
- Ability to customize feedback URL
- Ability to set the minimum authentication level needed to redeem an offer ("None", "Identified" or "Verified")
- Ability to enable/disable visual effects like confetti
<key>LMGConfig</key>
<dict>
<key>OfferBookmarkingEnabled</key>
<true/> // or <string>VerifiedOnly</string>
<key>OfferSharingEnabled</key>
<true/>
<key>BusinessSharingEnabled</key>
<true/>
<key>PoweredByGetintheLoopBadgeEnabled</key>
<true/>
<key>FeedbackLinksEnabled</key>
<true/>
<key>SupportEmail</key>
<string>support@loopmediagroup.com</string>
<key>RedemptionRequiresMinimumAudienceId</key>
<string>Identified</string>
<key>VisualEffectsEnabled</key>
<true/>
</dict>
Logging
The SDK comes with 5 built-in debug levels, from most detailed to most restricted logs: LMGDebugLoggerLevelVerbose
, LMGDebugLoggerLevelDebug
, LMGDebugLoggerLevelInfo
, LMGDebugLoggerLevelWarning
and LMGDebugLoggerLevelNone
.
By default it is set to LMGDebugLoggerLevelNone
.
- Objective-C
@import LMGUI;
...
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
... your app init code ...
[[LMGClient shared] setLoggerLevel:LMGDebugLoggerLevelDebug];
return YES;
}