# Are You Ready to go to Market
Source: https://resources.begenuin.com/commerce-media/Promote/are_you_ready_to_go_to_market
Launching your community within the Commerce Media Network is a pivotal step towards enhancing engagement and achieving your brand goals. Using the Genuin platform, you can effectively set up and optimize your community to connect with your audience and drive impactful results.
* **Define Your Community Goals**: Clarify what you aim to achieve with your community, such as increasing brand awareness, fostering user engagement, or driving sales.
* **Optimize Community Details**: Ensure that the community image, banner, and name reflect your brand’s identity and are visually appealing to attract and retain members.
* **Set Up Visibility and Access Controls**: Configure visibility settings to manage who can view and interact with your community, ensuring it aligns with your engagement strategy.
* **Create Engaging Content**: Plan and prepare content that will resonate with your audience, including updates, discussions, and media that reflect your community's purpose.
* **Invite Key Stakeholders**: Bring in key members, partners, and collaborators who can contribute valuable insights and drive activity within your community.
* **Test Your Setup**: Review all settings and features to ensure everything is functioning as intended before going live.
* **Promote Your Community**: Develop a marketing plan to announce your community’s launch, using channels such as social media, email newsletters, and your website.
* **Monitor and Adjust**: After launch, continuously monitor community activity and feedback, making adjustments as needed to enhance engagement and meet your goals.
With careful planning and the powerful tools provided by the Genuin platform, you are well-equipped to successfully launch and manage your community. By addressing these key aspects, you’ll be able to create an engaging environment that not only meets your Commerce Media Network’s objectives but also drives meaningful interactions with your audience.
# Best Practices - Multi Touchpoint Activation Examples
Source: https://resources.begenuin.com/commerce-media/Promote/best_practices_multi_touchpoint_activation_examples
Activating your community effectively requires engaging users through a variety of channels and touchpoints. By leveraging multiple strategies, you can create a comprehensive and immersive experience that maximizes interaction and fosters a strong connection with your audience.
* **Leverage Online Channels**: Boost engagement in your community by promoting it across social media platforms like Instagram, TikTok, YouTube, and more. Additionally, increase visibility by participating in relevant communities and inviting members to join and engage with your content.
* **Embed the Community into Your Platform**: Seamlessly integrate the community into your platform by using various embedding options such as Feed, Carousel, and Standard Wall. This allows you to maintain a consistent user experience while directing your customers to interact within your community space. By embedding the community, you enhance accessibility and encourage ongoing engagement directly through your platform.
* **IRL and Offline CTAs**: QR codes have found their place in marketing culture, offering a simple and effective way to enhance communication and engagement. You can position these codes at strategic locations such as store entrances, checkout areas, or promotional banners to facilitate easy access. Additionally, leverage QR codes for out-of-home advertising by including them on banners or posters to capture the attention of offline audiences. These QR codes will redirect users to your communities, making it easier for them to join and interact with your brand.
* **Influencer Collaborations**: Collaborating with influencers can significantly boost your community's visibility. Their endorsements and engaging content attract new members and energize existing ones. By leveraging their established followings, you can enhance your community's presence and drive growth.
* **Community Challenges**: Organize challenges or contests within your community to encourage participation and interaction. Highlight winners and top contributors to maintain excitement and engagement.
* **Content Partnerships**: Collaborate with other platforms or brands for content exchange or joint events. This cross-promotion can introduce your community to new audiences and enhance overall engagement.
* **Gamification**: Implement gamification elements such as badges, leaderboards, and rewards to make participation more engaging and fun. Recognize and celebrate member achievements to motivate continued involvement.
* **Interactive Webinars**: Host webinars to provide valuable insights and engage with your community in real-time. Promote these events across your platform and external channels to boost attendance.
Utilizing these multi-touchpoint activation strategies will help you build a more engaged and active community within your Commerce Media Network. By reaching out through diverse channels and innovative methods, you can enhance visibility, drive interactions, and achieve greater success in meeting your community goals.
# Add Admins
Source: https://resources.begenuin.com/commerce-media/build/add_admins
## What is an Admin?
An Admin is responsible for overseeing interactions within your community, ensuring that discussions remain productive, respectful, and aligned with your brand's guidelines. Admins help maintain a positive and engaging environment by managing content, addressing inappropriate behavior, and encouraging meaningful conversations.
In the context of your Commerce Media Network, adding admin allows you to delegate control and management within your community, ensuring that your advertisers and consumers can engage freely while maintaining the integrity and quality of the interactions.
### Difference between Creators and Admins
Creators create and organize community spaces, setting up content and fostering engagement. Admins oversee interactions within these spaces, ensuring discussions follow guidelines, resolving conflicts, and maintaining a positive environment. While Creators shape the community, Admins manage day-to-day interactions to keep the environment productive and respectful.
# Connect Your brand Network
Source: https://resources.begenuin.com/commerce-media/build/connect_your_brand_network
Building your endemic brand network and partnering with relevant and broader media entities can lead to more diverse and valuable content. This approach enhances engagement with your audience and unlocks new revenue opportunities, providing greater value and interaction within your ecosystem.
## Add Consumer Brands
1. **Log in to the Brand Control Center**.
2. During onboarding, go to Launch **Community Media Network > Consumer Brands**.
3. Click the **+ Add Brand** button.
4. Add Click on the **+ Add Brand** to Earn button and fill in the required information.
* **Search Brand or Add New Brand**: You can search the brand or add new brand by typing the name.
* **Contact Email**: You can add the Contact Emails of Your Consumer Brands
* **Website URL**: Enter the Brand’s business website.
* **Earnings**: CPM Floor Price: Insert the minimum amount you want to earn for every thousand impressions.
* **Community Access Period**: You can set the access period for consumer brand.
* **Social Media Handles**: You can add the social media handles(Youtube, Tiktok, and Instagram) of the consumer brands. These social media handles will help in curating or importing content for the brands which will be visible under your network.
5. After entering all required information, click Add to send an invitation to the brand for onboarding.
Alternatively, you can add consumer brands by navigating to Manage and then selecting Brands.
Note: Social media handles are essential for curating and importing content for the brands.
# How to White Label Your Community
Source: https://resources.begenuin.com/commerce-media/build/how to_white_label_your_community
To white-label your community and give it a personalized domain, follow these steps:
1. **Login to Brand Control Center**\
Start by logging into your Brand Control Center.
2. Navigate to White-Label Settings\
From the dashboard, go to:\
**Dashboard > Publish Brand Community > White Label Settings**.
3. Set Your White-Label Domain\
In the **White-Label Settings**, configure the domain for both your Production and QA environments.
Note:\
Ensure your [domain is properly connected](https://resources.begenuin.com/brands/settings#steps-for-setting-up-whitelabel) to avoid any issues with your white label setup.
This process allows you to fully customize your community’s branding under your own domain.
# How to Add Admins
Source: https://resources.begenuin.com/commerce-media/build/how_to_add_admins
1. **Log in to Brand Control Center**.
2. Go to **Manage > Communities**.
3. **Edit** the desired community.
4. Go to the **General** section.
5. Scroll to **Admins** and click **+ Add Admin**.
6. Search and add Admins to help manage and enhance your community.
# How to Create a Community
Source: https://resources.begenuin.com/commerce-media/build/how_to_create_a_community
Creating a community within your platform is a straightforward process that helps you foster engagement and bring your audience together. Follow these steps to get started:
1. **Log in to Brand Control Center**\
Begin by logging into your Brand Control Center.
2. Navigate to Community Management\
From the dashboard, go to:\
**Manage > Communities**.
3. Create a New Community\
Click on the "**New Community**" button to start setting up your community space.
4. Fill in Community Details\
You’ll need to provide key details such as:
* Community Image
* Banner
* Community Name
* Community Type
* Settings for visibility, including who can see the Loop.
Once you’ve completed these fields, your community will be ready to launch, enabling you to engage directly with your audience and align the space with your Commerce Media Network’s objectives.
# White Labeling Your Community
Source: https://resources.begenuin.com/commerce-media/build/white_labeling_your_community
White labeling allows you to customize a platform or service to reflect your brand identity, offering a seamless and personalized experience for your users. By using white labeling, you can present your community with your branding, logo, and design, making it appear as a fully integrated part of your network.
For your Commerce Media Network, white labeling ensures that your advertisers, partners, and consumers experience a unified brand presence, enhancing trust and engagement. It enables you to maintain full control over the look and feel of the community while utilizing powerful features in the background.
## Why White-Label Your Community?
White-labeling your community is a strategic move for any Commerce Media Network, allowing you to maintain a unified brand presence and deliver a personalized experience for your audience. By controlling how your platform looks and operates, you create a seamless journey that aligns with your brand values and business goals.

**Key Benefits**:
1. **Strengthen Brand Identity**: By white-labeling, you can fully customize your community’s interface, keeping it aligned with your brand’s visual elements, tone, and messaging.
2. **Enhance Trust and Credibility**: When users see a consistent brand across all touchpoints, it builds trust and credibility, reinforcing your standing as a key player in the industry.
3. **Improve User Experience**: With a custom-branded community, you can ensure a smooth and consistent experience for your members, making navigation and interaction feel more intuitive and engaging.
4. **Control Over Features and Functionality**: White-labeling allows you to choose the features and functions that best suit your Commerce Media Network, helping you cater to the specific needs of your advertisers, partners, and community.
5. **Monetization Opportunities**: A branded community gives you more control over ad placements, sponsorships, and other monetization strategies, allowing you to optimize revenue opportunities without relying on external platforms.
6. **Data Ownership**: With full control over your community, you retain ownership of all data, ensuring that insights gathered from interactions remain exclusive to your brand for targeted decision-making.
White-labeling your community gives you the freedom to shape the entire member experience. It ensures that every interaction, from the look and feel to the features used, reflects your brand’s identity, while empowering your Commerce Media Network to maximize engagement and business potential.
# Activate Your Community
Source: https://resources.begenuin.com/commerce-media/engage/activate_your_community
Activating your community involves encouraging engagement and participation through dynamic activities. Content and hashtag challenges are effective ways to stimulate interaction and foster a vibrant community.
**Content Challenges**
* **Best Product Review Challenge**: Encourage your community members to create and share detailed reviews of your brand’s products or services. This can provide valuable insights and showcase authentic user experiences.
* **Creative Campaign Pitch Challenge**: Invite members to submit ideas for innovative advertising campaigns or content themes. The best pitches can be featured or used in your community’s promotional efforts.
* **Industry Insight Blog Post Challenge**: Ask members to write and share blog posts on trending topics or industry insights. Highlighting these contributions can position your community as a thought leader in the field.
**Hashtag Challenges**
* **#MyBrandStory**: Encourage users to share personal stories or experiences related to your brand using this hashtag. This helps build emotional connections and showcases real-life impact.
* **#CMNTrendsetters**: Create a hashtag for members to post about the latest trends or innovations they’ve discovered in your industry. This fosters a culture of discovery and engagement.
* **#ExclusiveContentCreations**: Ask users to share their unique content, such as videos, infographics, or artwork, using this hashtag. It highlights creativity and provides a platform for members to showcase their work.
These challenges are designed to drive engagement and interaction within your Community Media Network, enhancing both involvement and brand presence.
# Add Members
Source: https://resources.begenuin.com/commerce-media/engage/add_members
## What is a Member?
A Member is someone who actively contributes to your community by creating and managing content within Groups.
While their role may overlap with that of a Creator, the key difference lies in their specific focus on supporting the content and engagement within Groups rather than managing the entire community.
Members are often experts, teammates, or partners who bring valuable insights, helping to foster ongoing discussions and keep the community engaged.
Unlike Creators, who oversee the entire community, including Groups, Members are more focused on driving activity within individual Groups.
By adding members, you can distribute responsibilities, leveraging their expertise to help your Commerce Media Network grow and succeed.
# How to Add and Manage Members
Source: https://resources.begenuin.com/commerce-media/engage/how_to_add_and_manage_members
1. **Login to Brand Control Center**.
2. Go to **Manage > Groups**.
3. **Edit** the desired Group.
4. Go to the Members section.
5. Click **+ Add Members**.
6. Search and add Members to help manage and enhance your community.
# What are Subscribers
Source: https://resources.begenuin.com/commerce-media/engage/what_are_subscribers
Subscribers are individuals who follow or join specific content areas, such as groups, within your community. They receive updates and notifications about new content and activities related to their interests, allowing them to stay engaged with the topics they care about.
As a Commerce Media Network, having subscribers helps drive interaction and build a dedicated audience around specific content themes. Subscribers increase visibility and engagement by consistently receiving and interacting with content that aligns with their preferences.
## View Subscribers
1. **Login to Brand Control Center**.
2. Go to **Manage > Groups**.
3. **Edit** the desired Group.
4. Go to the **Subscribers** section.
5. You can Search or View the subscribers of Group
# Benefits of Adding Community to Your Website or App
Source: https://resources.begenuin.com/commerce-media/overview/benefits_of_adding_community_to_your_website_or_app
Adding a community to your website or app can offer numerous benefits, enhancing user engagement, fostering brand loyalty, and driving growth. Here’s how integrating a community can be advantageous:
* **Enhanced User Engagement**: Integrating a community into your brand’s website or app encourages users to participate in discussions, share insights, and interact with content, including advertisements. This heightened engagement leads to increased interaction with your platform’s features, creating a more dynamic user experience.
* **Strengthened Brand Loyalty**: A community fosters a sense of belonging, making users more invested in your brand. When users feel connected to the network and its members, they are more likely to stay engaged and advocate for your platform, driving long-term loyalty and retention.
* **Valuable Market Insights**: Communities provide direct access to users, allowing you to gather feedback and better understand their preferences. These insights are crucial for refining ad strategies, improving targeting, and optimizing your platform’s offerings based on real user data.
* **Increased Platform Traffic**: An active community drives regular traffic to your brand’s website or app, as users return to engage with content, participate in discussions, and explore new features. This increased traffic can enhance your platform’s visibility and attractiveness to advertisers.
* **Opportunities for Targeted Monetization**: A vibrant community offers various monetization opportunities, such as premium memberships, exclusive content, or targeted advertising solutions. These revenue streams can boost the profitability of your Commerce Media Network while delivering value to users.
* **Enhanced Peer-to-Peer Interaction**: A community allows users to exchange knowledge and support one another. This peer-to-peer interaction leads to better user experiences and a more collaborative environment, reducing the need for extensive customer support and improving overall satisfaction.
* **Content Creation and Sharing**: Community members often generate and share content related to your platform's focus. This user-generated content can provide valuable insights, testimonials, and marketing material, contributing to your network’s credibility and appeal.
* **Facilitated Networking and Partnerships**: Adding a community feature helps users network and collaborate, potentially leading to new partnerships and business opportunities. This expands the reach and influence of your brand, benefiting both users and advertisers.
By incorporating a community into your Commerce Media Network’s website or app, you create a more engaging and valuable platform that enhances user interaction, provides valuable insights, and opens up new opportunities for growth and monetization.
# Example Use Case for Commerce Media Networks
Source: https://resources.begenuin.com/commerce-media/overview/example_use_case_for_commerce_media_networks
In the dynamic landscape of Commerce Media Networks, leveraging effective strategies to maximize engagement and drive revenue is crucial.
Understanding how to apply practical use cases can help commerce media brands to address the challenges and achieve their business objectives.
1. ## Brand Owned Community
* **Challenge**: Maintaining consistent brand messaging in a brand-owned community is difficult due to varying tones and styles from multiple contributors, like partners or influencers.
* **With Genuin**: Genuin’s open platform enables you to create and manage a branded community space that integrates seamlessly with your Commerce Media Network. This allows you to engage directly with your audience, foster discussions, and build a loyal community around your brand.
2. ## Aggregate and Centralize Content From the Social Handles
* **Challenge**: Scaling authentic content is challenging due to the complexities of sourcing, curating, and legally clearing UGC, and the difficulty of effectively repurposing it across community.
* **With Genuin**: Genuin offers tools to efficiently repurpose content from your social handles into your community space, ensuring broader reach and higher engagement within your Commerce Media Network.
3. ## Enhance Consumer Engagement
* **Challenge**: Engaging consumers meaningfully and maintaining their activity is tough due to the need for continuous, relevant content and dynamic interaction.
* **With Genuin**: You can enhance engagement using Genuin’s functionality of interactive campaigns, discussion, and surveys. These features will foster deep connections with your brand, encourage content sharing, and help expand your community through network effects.
4. ## Build Team of Community Builders
* **Challenge**: Identifying and managing persons who can effectively contribute to and grow your community requires effort and coordination.
* **With Genuin**: Genuin allows you to add and manage community builders efficiently. These key contributors can create and organize content, foster discussions, and drive engagement within your Commerce Media Network.
5. ## Boost Sales with Shoppable Ads
* **Challenge**: Driving traffic and increasing sales through effective ad placements within your community can be challenging.
* **With Genuin**: Genuin’s platform offers integrated shoppable ads and a social commerce solution that blends seamlessly with community content. This not only boosts traffic but also drives sales by making it easy for users to purchase directly through your Commerce Media Network.
6. ## Leverage QR Codes to Build Connections
* **Challenge**:Reaching offline audiences is difficult and costly, with the added complexity of integrating traditional or digital hoardings effectively to drive engagement and conversions.
* **With Genuin**: QR codes can be strategically placed in-store, on windows, or in other high-visibility areas to seamlessly connect users to your community or specific content within your Commerce Media Network. This approach enhances user engagement and simplifies access to your brand’s offerings.
# Take Back Control
Source: https://resources.begenuin.com/commerce-media/overview/take_back_control
Commerce Media Networks face the challenge of managing diverse data sources and optimizing ad performance across multiple channels. Genuin offers powerful tools and features designed to help Commerce Media Networks regain control over their advertising operations, data, and relationships with consumers, particularly in relation to “walled garden” platforms, communities, and social networks. This ensures more effective and efficient campaign management.
Here’s how Genuin supports them in achieving greater control and efficiency:
* **Centralized Data Integration**: Genuin seamlessly integrates data from various sources, allowing Commerce Media Networks to consolidate their information in one place. This centralized approach simplifies data management, providing a clear and comprehensive view of audience and campaign performance.
* **Advanced Targeting Capabilities**: With Genuin’s robust targeting features, Commerce Media Networks can precisely define and reach their desired audience segments. By leveraging detailed insights and analytics, they can craft more relevant and impactful advertising messages, enhancing engagement and effectiveness.
* **Cross-Channel Coordination**: Genuin facilitates the management of ad campaigns across multiple platforms and channels. Its tools ensure that Commerce Media Networks can coordinate their advertising efforts, creating a cohesive strategy that maximizes reach and impact.
* **Real-Time Insights and Analytics**: Genuin delivers actionable insights and real-time analytics, enabling Commerce Media Networks to make data-driven decisions. This level of insight helps them stay agile and responsive to market changes, optimizing strategies for better results.
* **Streamlined Campaign Management**: Genuin’s user-friendly interface and automation features simplify campaign management. By reducing manual tasks and streamlining processes, Commerce Media Networks can focus on strategic planning and creative execution, enhancing overall control and efficiency.
With Genuin’s comprehensive solutions, Commerce Media Networks can regain control over their advertising operations, confidently navigating the complexities of the digital advertising landscape to achieve greater ROI.
# What is a Commerce Media Network
Source: https://resources.begenuin.com/commerce-media/overview/what_is_a_commerce_media_network
A Commerce Media Network is an advertising platform that combines data from multiple sources, such as retailer websites, loyalty programs, and transaction data, to enhance the effectiveness of digital advertising. It enables brands and retailers to deliver highly personalized and measurable ad experiences, targeting consumers more precisely across the purchasing journey while maximizing the value of their media investments.
Here’s an overview of what a Commerce Media Network entails:
* **First-Party Data Aggregation**: A Commerce Media Network collects and integrates data from various sources, including different retailers, publishers, and third-party data providers. This aggregated data provides a more comprehensive view of consumer behavior and preferences.
* **Cross-Channel Advertising**: By leveraging a diverse data set, Commerce Media Networks enable advertisers to target audiences across multiple channels and platforms. This includes both online and offline channels, such as websites, social media, and physical retail locations.
* **Enhanced Targeting**: With access to a broad range of data, Commerce Media Networks can offer more precise and effective targeting options. Advertisers can reach specific audience segments based on their interests, behaviors, and purchase history.
* **Holistic Insights**: Commerce Media Networks provide advertisers with a unified view of their audience across different touchpoints. This helps in understanding the overall customer journey and optimizing ad strategies accordingly.
* **Improved ROI**: By combining data from multiple sources and channels, Commerce Media Networks help advertisers maximize their return on investment (ROI). The ability to target and measure ads more effectively leads to better campaign performance and efficiency.
Commerce Media Networks offer a more integrated approach to digital advertising by utilizing diverse data sources to enhance targeting, insights, and overall advertising effectiveness.
# Create a Community
Source: https://resources.begenuin.com/commerce-media/plan/create_a_community
A community is a collaborative space where members with shared interests can connect and engage. For instance, within your network, you might create a space focused on product discussions where users share experiences, offer insights, and interact with engaging content like tutorials or reviews.
Once your community is set up, you can invite members, such as partners or consumers, to join and contribute. This fosters an interactive environment that enhances engagement, driving meaningful connections across your Commerce Media Network.
To add a Community follow the below steps:
1. **Log in to the Brand Control Center**.
2. Navigate to **Manage > Communities**.
3. Click on **+ New Community**
4. Fill in the Following Information
* **Upload Banner/Image**: You can upload the Banner/Community Image
* **Community Name**: Insert the Community Name
* **Community Handle**: Insert the Community Handle
* **Purpose of This Community**: Add the Purpose of the community
* **Community Type**: Select the Community type to Private or Public
* **Who Can Create Groups**: Select the Group creation rights
5. After configuring the details, click on the “**Create**” button
# Create Your Brand Profile
Source: https://resources.begenuin.com/commerce-media/plan/create_your_brand_profile
As a Commerce Media Network, first creating a brand profile is vital to establishing your brand’s identity and ensuring consistent communication with your partners and advertisers.
A well-structured brand profile strengthens your network's positioning, fosters trust, and enhances engagement within the broader commerce ecosystem.
To create your brand profile, follow these steps:
1. **Log in to the Brand Control Center (BCC)**.
2. Navigate to **Settings > Brand Profile**.
3. Customize your profile by uploading your brand image, adding a bio, and entering your preferred URL. Additionally, link your phone number, website, and social media accounts to enhance visibility and connectivity.
This setup ensures that your brand’s presence is cohesive, professional, and aligned with your brand’s objectives, making it easier to engage with advertisers and partners.
# Intro to the Brand Control Center
Source: https://resources.begenuin.com/commerce-media/plan/intro_to_the_brand_control_center
The Brand Control Center (BCC) is an essential platform for Commerce Media Networks looking to streamline their advertising and content management.
As a user, you'll find the BCC to be a centralized hub where you can efficiently oversee and optimize all your campaigns. It consolidates data from multiple channels, giving you a comprehensive view of your brand’s performance.
With the BCC, you gain access to powerful tools for managing ad placements, tracking campaign metrics, and adjusting strategies in real time. This integration simplifies complex tasks, allowing you to maintain consistent messaging and make informed decisions that drive better results.
Whether you’re enhancing engagement or maximizing revenue, the BCC supports you with the insights and controls you need to succeed in the dynamic landscape of commerce media.
# Sign Up and Log In
Source: https://resources.begenuin.com/commerce-media/plan/sign_up_and_login
## Sign Up
Welcome to our platform! This guide will walk you through the steps to set up your account and brand profile. Let’s get started!
## Steps:
### 1. Enter Your Email and Password:
* Begin by entering your email address and password. Click on the "Agree and Continue" button to proceed.
### 2. Setup Your Brand Profile:
* Upload your brand image, enter your brand name, and choose your preferred URL to personalize your brand profile.
### 3. Enter Your Brand Name:
* Input your brand name, which will be displayed to your users.
### 4. Link Your Phone Number:
* Provide your phone number to link it with your account.
Once completed, you'll be logged into your account to start filling out your brand information.
## Login
Add email address and password to login into the Brand Control Center.
# What is a Creator
Source: https://resources.begenuin.com/commerce-media/plan/what_is_a_creator
A Creator is someone responsible for creating and managing collaborative spaces where members can interact and engage with content. They play a key role in shaping the experience within the community by organizing topics, fostering discussions, and driving meaningful connections.
For a Commerce Media Network, Creator helps ensure that brand messaging and engagement align with broader commercial goals.
## Who Can Be a Creator for Your brand?
Creators can be anyone who loves your brand—employees, loyal customers, influencers, or partners. For example, if your brand focuses on sustainable fashion, a Creator might be someone passionate about eco-friendly practices, leading discussions and sharing tips that resonate with your audience.
## What Can They Do?
While Creators in your Commerce Media Network do not have exclusive access to manage the entire community, they play a crucial role in overseeing Groups. This allows them to create and organize content, facilitate discussions, and ensure that Groups stay aligned with your brand’s overarching goals. By clearly defining their role, Creators can actively contribute to fostering meaningful connections and driving engagement within your Commerce Media Network.

# Add Group Members
Source: https://resources.begenuin.com/developers/add_collaborator
Add Collaborator API enables adding a new collaborator to a specified Loop, allowing them to contribute content and manage posts within the community.
**URL** : `/api/thirdparty/update_conversation/{chat_id}`
**Method** : `Patch`
**Auth required** : YES
**Note** : You need to Authorize [gn-access-token](https://resources.begenuin.com/developers/authentication) as `Bearer Token` to run the API.
# Request Body
```json theme={null}
{
"members_added": [
{
"user_id": "b12f13af-ef5a-4906-b0a0-2995e106200d"
}
],
"members_removed": [
"b12f13af-ef5a-4906-b0a0-2995e106200d"
],
"subscribers_removed": [
"b12f13af-ef5a-4906-b0a0-2995e106200d"
],
"name": "new name",
"description": "new description #abc #xyz",
"tags": "abc,xyz",
"dp": "1.png",
"topics": [
1,
2
],
"settings": {
"discoverable": false
}
}
```
## Success Response
**Condition**: If Everything is okay and collaborator is added.
**Code**: `200`
**Content**
```json theme={null}
{
"code": 200,
"message": "Conversation updated successfully.",
"data": {
"members_added": [
{
"member_id": "9a42d4ed-3720-49cb-8697-57d7e8269b9d",
"name": null,
"bio": null,
"nickname": null,
"phone": "9533333315",
"is_brand_system_user": false,
"is_avatar": true,
"status": 2,
"role": 2,
"profile_image": "sloth",
"profile_image_s": "",
"profile_image_m": "",
"profile_image_l": ""
}
],
"members_removed": [],
"subscribers_added": [],
"subscribers_removed": [],
"requester_removed": [],
"name_updated": false,
"description_updated": false,
"dp_updated": false,
"topics_updated": false,
"settings_updated": false
}
}
```
**Note**: In the `members_added` array, each object includes the `member_id`, which uniquely identifies the added Collaborators.
## Bad Request
**Condition**: The API returns an error response if the request contains invalid data or errors, preventing the collaborator from being added.
**Code**: `400`
**Content**
```json theme={null}
{
"code": "1099",
"message": "An unexpected error occurred processing the request",
"data": {}
}
```
## Unauthorized
**Condition**: The API returns an `unauthorized` response if the provided authentication credentials are invalid or missing.
**Code**: `401`
**Content**
```json theme={null}
{
"code": "5159",
"message": "Invalid Use of API",
"data": {}
}
```
## Internal Server Error
**Condition**: If an unexpected issue occurs on the server, an `Internal Server Error` is returned.
**Code**: `500`
**Content**
```json theme={null}
{
"code": "5158",
"message": "Could not update the conversation.",
"data": {}
}
```
# Add Community Members
Source: https://resources.begenuin.com/developers/add_member
Add Member API enables adding a new member to a community, granting them access to participate and engage with content within the platform.
**URL** : `/api/thirdparty/community/add_users`
**Method** : `POST`
**Auth required** : YES
**Note** : You need to Authorize [gn-access-token](https://resources.begenuin.com/developers/authentication) as `Bearer Token` to run the API.
# Request Body
```json theme={null}
{
"onboarding_communities": "any",
"communities": "any",
"single_tap_join": "any",
"invite_members": "any",
"join_request_approved": "any",
"users": "any"
}
```
## Success Response
**Condition**: If Everything is okay and the member is added.
**Code**: `200`
**Content**
```json theme={null}
{
"code": 200,
"message": "XXXX-[Members Added]",
"data": {
"members_added": [
{
"member_id": "c2fd91a1-faf8-48a8-9b3e-b2248c8acf21",
"name": null,
"bio": null,
"nickname": null,
"phone": "91943724335",
"is_brand_system_user": false,
"is_avatar": true,
"profile_image": "alien",
"profile_image_s": "",
"profile_image_m": "",
"profile_image_l": ""
},
{
"member_id": "bd7608b7-5c0b-4fcc-9799-5944de1b6f5d",
"name": null,
"bio": null,
"nickname": null,
"phone": "34684433270",
"is_brand_system_user": false,
"is_avatar": true,
"profile_image": "smiling_face_with_horns",
"profile_image_s": "",
"profile_image_m": "",
"profile_image_l": ""
}
]
}
}
```
**Note**: In the `members_added` array, each object contains a `member_id`, which uniquely identifies each added member.
## Bad Request
**Condition**: If the request contains errors or invalid data, resulting in video not posted.
**Code**: `400`
**Content**
```json theme={null}
{
"code": "1099",
"message": "An unexpected error occurred processing the request",
"data": {}
}
```
## Not Found
**Condition**: The API returns a not found response if the specified community or resource does not exist.
**Code**: 404
**Content**
```json theme={null}
{
"code": "5218",
"message": "The community you are looking for is no longer available.",
"data": {}
}
```
## Precondition Failed
**Condition**: The API returns a pre-condition failed response if required conditions, such as mandatory fields or criteria, are not met before adding the member.
**Code**: `412`
**Content**
```json theme={null}
{
"code": "5166",
"message": "XXXX-[Invalid Use of API]",
"data": {}
}
```
# Add Admins
Source: https://resources.begenuin.com/developers/add_moderator
Add Moderators API allows assigning a user as a moderator to manage content and maintain community guidelines within the platform.
**URL** : `/api/thirdparty/community/add_moderators`
**Method** : `POST`
**Auth required** : YES
**Note** : You need to Authorize [gn-access-token](https://resources.begenuin.com/developers/authentication) as `Bearer Token` to run the API.
# Request Body
```json theme={null}
{
"community_id": "any",
"users": "any"
}
```
## Success Response
**Condition**: If Everything is okay and moderator is added.
**Code**: `200`
**Content**
```json theme={null}
{
"code": 200,
"message": "XXXX-[Members Added]",
"data": {
"moderators_added": [
{
"name": null,
"bio": null,
"nickname": null,
"is_brand_system_user": false,
"is_avatar": true,
"profile_image": "dog_face",
"profile_image_s": "",
"profile_image_m": "",
"profile_image_l": "",
"member_id": "8bf08f1f-9fb6-445b-85b4-156f19f6ae8b",
"role": 3
}
]
}
}
```
**Note**: In the `moderators_added` array, each object includes a `member_id`, which uniquely identifies the added moderators.
## Bad Request
**Condition**: If the request contains errors or invalid data, resulting in video not posted.
**Code**: `400`
**Content**
```json theme={null}
{
"code": "1099",
"message": "An unexpected error occurred processing the request",
"data": {}
}
```
## Not Found
**Condition**: The API returns a not found response if the specified moderator or community does not exist.
**Code**: 404
**Content**
```json theme={null}
{
"code": "5218",
"message": "The community you are looking for is no longer available.",
"data": {}
}
```
## Precondition Failed
**Condition**:
**Code**: `412`
**Content**
```json theme={null}
{
"code": "5166",
"message": "XXXX-[Invalid Use of API]",
"data": {}
}
```
# Authentication
Source: https://resources.begenuin.com/developers/authentication
The **Authentication** API provides users with a secure access token. This token is essential for running other APIs within the application.
**URL** : `/api/thirdparty/auth`
**Method** : `POST`
**Auth required** : YES
**Mandatory Fields** : api\_key, api\_secret
**Obtain Your API Key**: Contact the Genuin team to obtain your unique API\_KEY. This key is essential for authenticating your application with the Genuin service.
# Request Body
```json theme={null}
{ "api_key": "YOUR_API_KEY", "api_secret": "YOUR_API_SECRET" }
```
## Success Response
**Condition**: If `api_key` and `api_secret` are okay, `gn-access-token` will be generated in the `Body` > `Header`.
**Code**: `200`
**Note**: Only with the help of this `gn-access-token`, you will be able to use other APIs
## General Error
**Condition**: If the request contains errors or invalid data, authentication will fail.
**Code**: `400`
Content
```json theme={null}
{
"code": "1099",
"message": "An unexpected error occurred processing the request",
"data": {}
}
```
## Parameters Missing
**Condition**: - If required parameters are missing, authentication will not be processed.
**Code**: 404
**Content**
```json theme={null}
{
"code": "5235",
"message": "Brand not exists.",
"data": {}
}
```
## Precondition Failed
**Condition**: If a precondition is not met, the authentication process will be denied, preventing further access.
**Code**: `412`
**Content**
```json theme={null}
{
"code": "5166",
"message": "XXXX-[Invalid Use of API]",
"data": {}
}
```
# Create community
Source: https://resources.begenuin.com/developers/create_community
The Create Community API enables developers to create a new community within the platform programmatically. This API is crucial for automating community setup, allowing for seamless integration with your application or service.
**URL** : `/api/thirdparty/community/create`
**Method** : `POST`
**Auth required** : YES
**Mandatory Fields**: handle, name, type, actions
**Note** : You need to Authorize [gn-access-token](https://resources.begenuin.com/developers/authentication) as `Bearer Token` to run the API.
# Request Body
```
{
"handle": "genuin-community",
"name": "Genuin Community",
"description": "some community description #genuinCommunity #genuinAmdCommunity",
"tags": "genuinCommunity,genuinAmdCommunity",
"dp": "1.png",
"categories": {
"existing": [
1,
2
],
"new": [
"abc",
"aAa",
"xYZ"
]
},
"is_ai_generated": false,
"is_ai_generated_dp": true,
"is_ai_generated_banner": true,
"banner": "1.png",
"users": [
{
"user_id": "b12f13af-ef5a-4906-b0a0-2995e106200d"
}
]
}
```
## Success Response
**Condition**: If Everything is okay and community is created.
**Code**: `200`
**Content**
```json theme={null}
{
"code": 200,
"message": "XXXX-[Community has been created successfully.]",
"data": {
"community_id": "0a2be302-04af-4642-a436-1612554e48a6",
"share_url": "https://community.dhruvpatel.com/community/dqwd-w5oa",
"dp": "https://media.qa.begenuin.com/uploads/profile_images/community/eeqfwee12.png",
"banner": "https://media.qa.begenuin.com/uploads/community/banner/dqwdq.png",
"color_code": "#A4E6DA",
"text_color_code": "#49CDB5",
"leader": {
"member_id": "0bf977ed-4887-4056-a8f4-1f0de71101f1",
"name": "hoo hwwoo",
"bio": "jai hwwooo",
"nickname": "wdqwdqwdq",
"phone": "91333333333333",
"is_brand_system_user": true,
"is_avatar": false,
"brand": {
"brand_id": 1,
"brand_slug": "dqwd-dqjb"
},
"profile_image": "https://media.qa.begenuin.com/uploads/profile_images/1706610191569_Vector.png",
"profile_image_s": "https://media.qa.begenuin.com/uploads/profile_images/s/1706610191569_Vector.png",
"profile_image_m": "https://media.qa.begenuin.com/uploads/profile_images/m/1706610191569_Vector.png",
"profile_image_l": "https://media.qa.begenuin.com/uploads/profile_images/l/1706610191569_Vector.png"
}
}
}
```
**Note**: In the `community_id` you will get the actual ID of community and the link from `share_url`
## Bad Request
**Condition**: If the request contains errors or invalid data, resulting in the community not being created.
**Code**: `400`
**Content**
```
{}
```
## Invalid API Usage
**Condition**: "If the community categories do not exist or there is invalid use of the API, a `404` or `412` error is returned, respectively.
> Category Doesn't exists
**Code**: `404`
**Content**
```json theme={null}
{
"code": "5220",
"message": "XXXX-[community categories does not exists.]",
"data": {}
}
```
> Invalid Usage of API
**Code**: `412`
**Content**
```json theme={null}
{
"code": "5166",
"message": "XXXX-[Invalid Use of API]",
"data": {}
}
```
## Internal Server Error
**Condition**: If an unexpected issue occurs on the server, an `Internal Server Error` is returned.
**Code**: `500`
**Content**
```json theme={null}
{
"code": "5216",
"message": "XXXX-[community handle already exists.]",
"data": {}
}
```
# Create Group
Source: https://resources.begenuin.com/developers/create_loop
The **Create Group** API enables quick setup of collaborative spaces called Groups, where collection of videos organized around a specific theme or topic.
**URL** : `/api/thirdparty/group/create`
**Method** : `POST`
**Auth required** : YES
**Mandatory Fields**: type, Community\_id
**Note** : You need to Authorize [gn-access-token](https://resources.begenuin.com/developers/authentication) as `Bearer Token` to run the API.
# Request Body
```json theme={null}
{
"type": 4,
"chat_id": "456e7890-b12c-4c23-89ef-126314214567",
"recorded_video": {
"message_id": "789e1234-f12d-4c67-a256-126314214555",
"video_name": "abcd1234-5678-90ef-1112-234567890111_video.mp4",
"thumbnail_name": "abcd1234-5678-90ef-1112-234567890111_thumb.jpg",
"video_path": "trends_videos/2024/5/6/creative",
"thumbnail_path": "trends_thumbnail/2024/5/6/creative",
"is_ai_generated_video": true,
"is_ai_generated_thumbnail": true,
"link": "",
"size": "5MB",
"duration": 5,
"aspect_ratio": "720x1280",
"resolution": "1080p",
"description_text": "Hello, this is @user and I love community XYZ",
"description_data": "[\"Hello\",{\"user_id\":\"345e1234-5678-90ef-2345-678912341234\"},\"and I love community\",{\"community_id\":\"def45678-abcd-ef12-3456-1234abcdef56\"}]",
"meta_data": {
"topic": "Open Discussion"
}
},
"community_id": "f2a05adb-93ce-4a19-b003-3523fa745667",
"actions": [
{
"action_id": 3,
"access_type_id": 5
},
{
"action_id": 5,
"access_type_id": 9
}
],
"group": {
"name": "Tech Conversations",
"description": "A platform for discussing the latest in technology and innovation.",
"tags": "technology",
"dp": "group_dp.png",
"topics": [1, 2],
"members": [
{
"phone_number": "919876543210"
},
{
"user_id": "abcd1234-5678-90ef-1112-234567890111"
}
]
},
"settings": {
"discoverable": false
},
"template_id": 2,
"is_ai_generated": false
}
```
## Success Response
**Condition**: If Everything is okay and group is created.
**Code**: `200`
**Content**
```json theme={null}
{
"code": 200,
"message": "Group has been created successfully.",
"data": {
"chat_id": "456e7890-b12c-4c23-89ef-126314214567",
"type": 4,
"settings": {
"discoverable": true
},
"share_url": "https://app.qa.begenuin.com/group/rhythm-and-tech-conversations-ap55?community=456e7890abcdef",
"is_welcome_loop": false,
"group": {
"group_id": "f67c89d0-9abc-4abc-bdef-56789abcf456",
"group_name": "Tech Conversations",
"group_description": "A platform for discussing the latest in technology and innovation.",
"color_code": "#FF5733",
"text_color_code": "#C70039",
"dp": "https://media.qa.begenuin.com/uploads/profile_images/tech/conversation.png",
"dp_s": "https://media.qa.begenuin.com/uploads/profile_images/tech/conversation_s.png",
"dp_m": "https://media.qa.begenuin.com/uploads/profile_images/tech/conversation_m.png",
"dp_l": "https://media.qa.begenuin.com/uploads/profile_images/tech/conversation_l.png",
"no_of_members": 1,
"members": [
{
"member_id": "abcd1234-5678-90ef-1112-234567890111",
"name": null,
"username": "tech_leader",
"is_avatar": true,
"is_brand_system_user": false,
"status": 1,
"role": 1,
"profile_image": "alien",
"profile_image_s": "",
"profile_image_m": "",
"profile_image_l": ""
}
]
},
"latest_message_at": "1727169211000",
"unread_message_count": 0,
"latest_messages": [
{
"owner": {
"member_id": "345e6789-12ab-4567-8def-90abcdef1234",
"username": "tech_leader"
},
"media_url": "https://media.qa.begenuin.com/temp_video/tech_discussion_video.mp4",
"thumbnail_url": "https://media.qa.begenuin.com/uploads/thumbnails/tech_thumb.jpg",
"thumbnail_url_s": "",
"thumbnail_url_l": "",
"media_url_m3u8": null,
"message_id": "234e5678-abcd-4e56-90ef-abcdef123456",
"message_at": "1727169211000",
"share_url": "https://app.qa.begenuin.com/video/tech-discussion-0jy0?community=abcdef123456&group=abcdef7890"
}
],
"brand_id": null,
"community": {
"community_id": "f2a05adb-93ce-4a19-b003-3523fa745667",
"handle": "tech_community",
"name": "Tech World",
"description": "A hub for all things technology. #TechWorld #TechCommunity",
"color_code": "#FF5733",
"text_color_code": "#C70039",
"dp": "https://media.qa.begenuin.com/uploads/profile_images/community/tech_community.png",
"dp_s": "https://media.qa.begenuin.com/uploads/profile_images/community/s/tech_community.png",
"dp_m": "https://media.qa.begenuin.com/uploads/profile_images/community/m/tech_community.png",
"dp_l": "https://media.qa.begenuin.com/uploads/profile_images/community/l/tech_community.png",
"share_url": "https://app.qa.begenuin.com/community/tech_community"
}
}
}
```
**Note**: `chat_id` is the unique identifier for a Group, and you can obtain the URL from the `share_url`.
## Bad Request
**Condition**: If the request contains errors or invalid data, resulting in the group not being created.
**Code**: `400`
**Content**
```
{}
```
## Internal Server Error
**Condition**: If an unexpected issue occurs on the server, an `Internal Server Error` is returned.
**Code**: `500`
**Content**
```json theme={null}
{
"code": "5026",
"message": "Could not find the video.",
"data": {}
}
```
# Off Site
Source: https://resources.begenuin.com/developers/guides/ad_creatives
You got the Post’s on your platform and you want to put it on your website as an advertisement? Use our Off Site functionality to create the advertisement. Here is how you can do it.
## Create New Ad
Click on the **+New Ad** button, and you can Select the Post to create an ad.

You can Search for the post, **Apply Filter** or you can check the Community and Group name by hovering over the post.

After selecting the post, click on the **Next** button for the further process.
Here you can add the Additional Details for each post like:

* **Ad Copy**: This is kinda introduction regarding your post.
* **Call-to-Action**: You can add the Button name and URL for the Call-to-Action.
* **Fetch Metadata**: Checkmark this option to fetch metadata.
* **Hashtags**: You can add the hashtags for the post.
* **Pixel URL**: You can add the pixel URL to track the details like view page, button clicked or much more.
After adding the Additional Details click on the **Next** button and you can view the Preview of Post. You can also configure the following details.

* **Ad Name**: Insert the name of your ad for your reference.
* **Google Tag Manager ID**: Insert tag manager id to manage tracking tags efficiently.
* **Size**: Select the dimension of creative.
* **Button Delay**: Select the delay duration to display the CTA button.
* **Redirect to Profile**: The post within the Ad, will have the profile of creator. Switch off this option if you don’t want to user to redirect whenever they click on the profile icon.
* **Enable Engagement Tools**: Switch off this option to disable the Repost, Spark, Comments, and Share options.
* **Autoplay Video**: Switch off this option to pause the autoplay.
### Edit Post

If you want to change the post selection for the ad then by clicking on the Edit Post button, you can change the post.
### Save and Update
Once you are finalized with the details, you can Save it and view the embed code.

### View Code
By clicking on the View Code button, you can generate the tag for the Off Site and embed it to your website.

### Edit Ad
If you want to Edit any Ad details, click on the **Edit Ad** under the More option. You can edit any details of the ad or select the new post for the ad.

## Deactivate/Reactivate Ads
If you want to stop your ads from being displayed then you can deactivate it by clicking on the **Deactivate** under the **More** option. The ads will stop working after this.

Now, if you want to restart your ads then you can again reactivate it by clicking on the **Reactivate** under the More option. The ads will start working again.

# Front Demonstration
After embedding the code, ads will be visible on the website.

## Full Screen View

# Change Logs
Source: https://resources.begenuin.com/developers/guides/change_logs
Track the latest updates, improvements, and fixes with our concise change logs.
**V 1.0.11**
* Carousel view changes in SDK
**V 1.1.1.1**
* Deeplink Handling in SDK
**V 1.1.2**
* Integrating Go APIs
* Advertisement Implementation
* Enhancement and Bug Fixes
**V 1.1.3**
* Bug Fixes and Enhancements
**V 1.1.4**
* Custom SSO Changes
**V 1.1.5**
* Bug Fixes and Enhancements
**V 1.1.6**
* Implemented the standard wall feed for improved content display.
* Bug Fixes and Enhancements
**V 1.1.6.2**
* Bug Fixes and Enhancements
**V 1.1.6.4**
* Linkout will appear after 10 seconds
**V 1.1.7**
* Enhanced brand profile API
* Email as a default login way
* SMS invitation by brands to non-Genuin users
**V 1.1.8**
* Updated icons for a refreshed look
* Enhanced Linkout styling for a more seamless experience
**V 1.1.9**
* Comment text now appears directly in the notification center for added clarity
* Enhanced view in Group Feed and Comments
**V 1.1.10**
* Picture-in-Picture (PIP) view enabled for watching videos while multitasking
* Extended video length to 5 minutes
* Clicking a notification highlights the comment, whether from the notification or the notification center
* Bug Fixes and Enhancements
**V 1.1.10.2**
* Updated authentication flow with refined SSO parameters
* Added support for seamless navigation via deeplinks
**V 1.1.10.5**
* Bug Fixes and Enhancements
**V 1.1.10.8**
* Bug Fixes and Enhancements
**V 1.1.11**
* Added comment highlight during creation for better visibility
* Community/Group name character limit updated to 40
* Bug Fixes and Enhancements
**V 1.1.12**
* Introduced [Contextual Feed](https://resources.begenuin.com/developers/sdk-docs/android_sdk#carousel-embed) for more relevant content delivery
* Bug Fixes and Enhancements
**V 1.1.12.2**
* Bug Fixes
**V 1.1.12.3**
* Improved [Contextual Feed](https://resources.begenuin.com/developers/sdk-docs/android_sdk#carousel-embed) for more relevant content
* Added callback handlers for [SSO login/logout](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handle-sso-login-explicitly-in-sdk)
* Bug Fixes
**V 1.1.12.8**
* Bug Fixes and Enhancements
**V 1.1.14**
* Brands now have more control over the video player experience, including options for autoplay, link delay, video loop, and swipe behavior.
* Brands can now enable or disable transcripts based on their own technical setup.
* Bug Fixes and Enhancements
**V 1.1.15**
* Navigate and engage effortlessly with new gesture-based controls.
* Community admins can now pin groups to highlight key conversations.
* Long press on video edges to skim through content faster.
* Bug Fixes and Enhancements.
**V 1.1.15.1**
* QA Environment support
**V 1.1.16**
* **Join Communities & Groups** right from your feed.
* **Auto-subscribe** to Groups when you join.
* “**Surprise Me**” button added during onboarding to auto-select interests.
* Revamped Profile Settings with easy access to **Personalization** & more.
**V 1.1.17**
* Location based contextual Embed.
* Video views will be calculated at 3 secs now.
* Change the configs of carousel design.
**V 1.1.17.3**
* Introduced Adaptive Video Display. Now you can change the aspect ratio of your videos to show in video player via BCC.
**V 1.0.15**
* Carousel view changes in SDK
**V 1.1.0**
* Xcode 16 Support for iOS SDK
* Terminology Updates: We’ve streamlined terms across the platform for better clarity:
* **Loops** are now **Groups**
* **Community Members** are now **Members**
* **Group Members** remain **Members**
* **Community Builder** is now **Creator**
* **Loop Collaborator** is now **Admin**
* **Community Leader** is now **Admin (Owner)**
* Bug Fixes
**V 1.1.1**
* Ads Integrations:
* Pre-Roll
* Mid-Roll
* End-Roll
* Support for Ads in Embed
* Bug Fixes and Enhancements
**V 1.1.2**
* Bug Fixes and Enhancements
**V 1.1.3**
* Custom SSO Changes
**V 1.1.3.1/1.1.3.2**
* Added push token support for seamless auto-login
**V 1.1.4**
* Clicking a notification highlights the comment, whether from the notification or the notification center
* Implemented the standard wall feed for improved content display
* Bug Fixes and Enhancements
**V 1.1.4.1**
* Bug Fixes and Enhancements
**V 1.1.5**
* Added focusing view to Carousel
* Bug Fixes and Enhancements
**V 1.1.6/1.1.6.1**
* Added focusing view to Carousel
* Linkout will appear after 10 seconds
**V 1.1.7**
* Enhanced brand profile API
* Email as a default login way
* SMS invitation by brands to non-Genuin users
* Enhanced link opening style for a smoother experience
**V 1.1.8**
* Updated icons for a refreshed look
* Enhanced Linkout styling for a more seamless experience
<>
**V 1.1.9**
* Improved data handling for embedded content
* Comment text now appears directly in the notification center for added clarity
* Enhanced gesture support for smoother interactions
* Enhanced view in Group Feed and Comments
* Bug Fixes and Enhancements
**V 1.1.9.1**
* Bug Fixes and Enhancements
**V 1.1.10**
* Extended video length to 5 minutes
* Bug Fixes and Enhancements
**V 1.1.10.1**
* Updated authentication flow with refined SSO parameters
* Added support for seamless navigation via deeplinks
**V 1.1.10.2**
* Bug Fixes and Enhancements
>
**V 1.1.11**
* Community/Group name character limit updated to 40
* Bug Fixes and Enhancements
**V 1.1.12**
* Introduced [Contextual Feed](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#carousel-embed) for more relevant content delivery
* Bug Fixes and Enhancements
**V 1.1.12.4**
* Improved [Contextual Feed](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#carousel-embed) for more relevant content
* Added callback handlers for [SSO login/logout](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#handle-sso-login-explicitly-in-sdk)
* Bug Fixes
**V 1.1.12.9**
* Bug Fixes
**V 1.1.14**
* Brands now have more control over the video player experience, including options for autoplay, link delay, video loop, and swipe behavior.
* Brands can now enable or disable transcripts based on their own technical setup.
* Bug Fixes and Enhancements
**V 1.1.15**
* Navigate and engage effortlessly with new gesture-based controls.
* Community admins can now pin groups to highlight key conversations.
* Long press on video edges to skim through content faster.
* Bug Fixes and Enhancements
**V 1.1.15.1**
* QA Environment support
**V 1.1.16**
* **Join Communities & Groups** right from your feed.
* **Auto-subscribe** to Groups when you join.
* “**Surprise Me**” button added during onboarding to auto-select interests.
* Revamped Profile Settings with easy access to **Personalization** & more.
**V 1.1.17**
* Location based contextual Embed.
* Video views will be calculated at 3 secs now.
* Change the configs of carousel design.
**V 1.1.17.1**
* Introduced Adaptive Video Display. Now you can change the aspect ratio of your videos to show in video player via BCC.
**V 2.0**
* With this update, we’ve introduced modularisation. Now, users can include only the SDK modules they need, instead of integrating the full package.
The SDK is modularized into:
* Core SDK
* UI SDK
* Camera SDK
* AI SDK
This gives you more flexibility, lighter builds, and faster integration.
**V 2.0.1**
* SSO Optimisation
**V 2.0.2**
* Client side Ads
**V 2.0.2.1**
* Minor bug fixes and enhancements.
**V 2.0.2.2**
* Minor bug fixes and enhancements.
**V 2.0.2.4**
* Minor bug fixes and performance enhancements.
**V 2.1.0**
* Introduced placement and other performance enhancements.
**V 2.1.0.1**
* Changes for implementing dynamic contextual parameters.
**V 2.1.0.2**
* Changes for implementing dynamic contextual parameters.
**V 2.1.0.3**
* Font and bug fixes update.
**V 2.1.0.4**
* Bug fixes update.
**V 2.0**
* With this update, we’ve introduced modularisation. Now, users can include only the SDK modules they need, instead of integrating the full package.
The SDK is modularized into:
* Core SDK
* UI SDK
* Camera SDK
* AI SDK
This gives you more flexibility, lighter builds, and faster integration.
**V 2.0.1**
* SSO Optimisation
**V 2.0.2**
* Client side Ads
**V 2.1.0.1**
* Contextual Parameter changes to support dynamic parameters.
**V 2.1.0**
* Introduced placement and other performance enhancements.
**V 2.1.0.1**
* Changes for implementing dynamic contextual parameters.
**V 2.1.0.2**
* Changes for implementing dynamic contextual parameters.
# Clip IT
Source: https://resources.begenuin.com/developers/guides/clipit
Got a long video and you want to cut out the clips to post it on your social media account. Genuin’s ClipIt feature is here to help you out. Here is how it will work
Navigate to the **Engage Engine > Import Videos > Clip It section**.
Here you can add a link of video to create short clips out of it. OR You can upload the video from **Computer**, **Google drive**, **Dropbox**, or **s3 Bucket**.
> **Note**: The duration of video shall be less than 30 minutes or 2gb in size.
Once you have added the video, you can apply these features to the video: Add Caption, Add Title, Add Background Music, Clickbait Thumbnail, and Smart Crop.
## Add Caption and Title
Checkmark **Add Caption** feature to add the cation to the generated clip from your video. This will add captions to each of your clips. And Checkmark the **Add Title** feature to add the title which will be based on the content of your video.
## Add Background Music
If you want to add the background music to the video then enable this option. Each generated clip will have the background music.
## Clickbait Thumbnail
If you want to generate the thumbnail with text then enable this feature. Thumbnail would be the best frame fetched from the video and the text will be applied which will be related to the video. Here is an example of it.
## Add Smart Crop
Smart crop features crop out the person from the video and displays in such a way that more focus is on the person who is talking. Below are some examples of it.
## Virality Score
## Scoring Criteria
Each video is assessed according to four major criteria.
### 1. Hook
The hook is used to mean the introductory segment of the video that may span up to 3 to 10 seconds. This should create a way in which someone viewing this clip can be compelled to keep watching the video. Creating a strong hook is important to retain viewers in this fast- paced online world.
**Score Range**: 0 to 100 points
### 2. Flow
Flow describes order and continuity of the video. While every video presentation should have a good flow of ideas, this means one point flowing seamlessly to another in the video. This aspect focuses on how effectively the message or the story is presented so that it does not get distorted or the audience lost.
**Score Range**: 0 to 100 points
### 3. Value
Value is the overall benefit or usefulness of the video provided to the viewer. It could be informational: educational or entertaining or motivating – or presented as delivering new and useful information. The idea is to know whether the viewer gets more than he or she expected in the video, and whether the video met its objectives.
**Score Range**: 0 to 100 points
### 4. Trend
Trend involves evaluating the degree to which the video is relevant to the current social trend or even the platform specific trends. A video based on trending topics has the chance of attracting more people’s attention and gathers more interaction.
**Score Range**: 0 to 100 points
## Upcoming Features
1. **Dynamic Text Adjustment**: This feature lets you re-sizes, repositions, and re-arranges different pieces of text in order to accommodate the video content and the space available, if any. It helps place the text without distortion of any significant images.
For example, score banner in a live match. It ensures that important text blocks, such as the score and other numbers, do not interfere with the game but remain easy to read and comprehend.
2. **Non-Transcribable Video Processing** : This feature can deal with videos that have insufficient audio or no verbal conversations at all so that they are still analyzed and processed.
For example in the case of a Mr. Bean or Charlie Chaplin episode which is primarily a visual humor, the system is able to understand the character’s actions like, for instance his facial expressions or gestures for the purposes of captioning or summarizing these images.
3. **Custom Caption Styles**: With the help of Custom Caption Styles, you can enhance the aesthetic of video captions with various fonts, colors and animations. This ensures that each text adheres to the theme and branding of the video’s content.
For instance, important messages can be made bold with vivid colors, and animated to appear through a fade-in effect combined with text effects.
4. **Generative B-rolls**: Generative B-Roll adds extra video clips related to the main content of the video to make it interesting. It will generate b-roll images or videos according to the user prompt.
For instance, when you talk about a certain travel place, it may include the video clips of famous historical buildings or the general atmosphere of the place.
5. **Transitions**: Transitions improve your video by incorporating smooth effects, like fades or cuts, in between the clips. This feature helps in making a fluent connection in the content, making it interesting for the audience.
For instance, a fade transition helps in a lovingly delicating movement from one frame to the other looking very neat and professional.
6. **GIFs, Emojis & Stickers**: Incorporation of GIFs, emojis, and stickers help in making their videos lively and relatable. This particular aspect lets you add some relatable visuals that are likely to appeal to the viewer.
For example, you could use a laughing emoji or an adorable sticker while making a funny face to emphasize on the comic moments or show flying money emoji to depict some financial concept, or highlight important aspects of your clip.
7. **Overlays**: Overlays let you add branding elements like a logo, text, or even images into the video. This feature assists in maintaining the visual as well as the brand identity for the duration of the video.
For instance, one can tuck their logo away in a corner or include a text overlay with a call to action for the audience.
8. **Sound Effects**: Sound Effects enhance the overall quality and presentation of a video by incorporating sound effects that emphasize key moments. This serves to enhance the enjoyment of the audience and also helps in focusing their attention.
For instance, you can use "ding" sound when something new appears or a funny sound to a silly scene to make it more entertaining.
9. **Schedules**: The Schedule feature automatically picks up videos whenever they are uploaded to Drive, AWS S3, or Dropbox. It processes these videos according to a set schedule, preparing clips for review. This ensures timely access to content without manual intervention.
For example, if you have uploaded one video to Drive, AWS S3, or Dropbox, the Schedule feature automatically picks them up. It processes them into clips based on your set schedule, ready for review.
10. **Multi-lingual Clips**: Multi-lingual Clips produce video material with captions or dubbed sound in different languages. This added functionality ensures that your videos reach a much broader audience consisting of speakers of various languages.
For instance, once clips are generated, they can be translated into 100+ supported languages. This ensures your content is accessible to a global audience in their native languages.
11. **Editor**: With the help of an editor you can cut your video clips, trim it, or add effects and audio. This feature allows you to enhance the quality of video with multiple editing options.
For instance, you may level the audio, add effects, and use transition to improve the overall video quality.
# OnSite
Source: https://resources.begenuin.com/developers/guides/embed
Embedding your brand’s community platform allows you to seamlessly integrate your community and content into your website, enhancing engagement and visibility. This guide will walk you through the main features and steps to get your embed set up, whether you're an experienced user or just getting started.
## Getting Started:
### Step 1: Login to Brand Control Center
Start by logging into your Brand Control Center and navigating to the **Grow > On Site** section.
### Step 2: Click on +New Embed
Begin by selecting the option to create a new embed.
### Step 3: Name Your Embed
Enter a unique name for your embed. This will help you easily identify it later.
### Step 4: Choose Your Embed Type
Select from three distinct types:
Select this type if you want to display the entire brand feed.
Select this type if you want to display just the community feed.
Select this type if you want to display just the group feed of particular community.
### Step 5: Choose Your Embed Style
Select from three distinct styles:
Display your content in a traditional grid format.
***Settings***
**Embed Size**: Specify the width and height for the embed to ensure it fits perfectly within your website’s layout.
**Show Navigation**: Choose whether to include navigation controls.
**Enable Engagement Tools**: Enable this to display the Repost, Spart, Comment, and Share.
**Show Links**: Enable this option if you want to make linkouts visible.
**Group Video**: Enable this feature to auto play the video.
Showcase your content in a continuous scroll, similar to social media feeds.
***Settings***
**Headline**: Insert the Headline you want to display on Embed
**Sub-Headline**: Insert the Sub-Headline you want to display on Embed
**Button**: Enable this option if you want to show the button and fill in the below details.
**Button Text**: Insert the button text you want to display
**Button URL**: Insert the URL where you want to redirect the user whenever the button is clicked
**Embed Size**: Specify the width and height for the embed to ensure it fits perfectly within your website’s layout.
**Enable Floating View**: Enable this option if you want to have the floating view on the page whenever the user closes the post.
**Show Username**: Enable this option if you want to show the user name of the video creator
**Show View Count**: Enable this option if you want to show the view count of the post
**Enable Engagement Tools**: Enable this to display the Repost, Spart, Comment, and Share
**Show Social Interaction Data**: Enable this option to display the count of Spark, Comments, and Share.
**Show Links**: Enable this option if you want to make linkouts visible.
**Position**: Select where you want to display the link. From Outside or Overlay
**Autoplay Video**: Enable this option to autoplay the video
**Group Video**: Enable this option to replay the video until any other video is played
Highlight featured content with a rotating display.
***Settings***
**Headline**: Insert the Headline you want to display on Embed
**Sub-Headline**: Insert the Sub-Headline you want to display on Embed
**Button**: Enable this option if you want to show the button and fill in the below details.
**Button Text**: Insert the button text you want to display
**Button URL**: Insert the URL where you want to redirect the user whenever the button is clicked
**Embed Size**: Specify the width and height for the embed to ensure it fits perfectly within your website’s layout.
**Enable Floating View**: Enable this option if you want to have the floating view on the page whenever the user closes the post.
**Show Username**: Enable this option if you want to show the user name of the video creator
**Show View Count**: Enable this option if you want to show the view count of the post
**Enable Engagement Tools**: Enable this to display the Repost, Spart, Comment, and Share
**Show Social Interaction Data**: Enable this option to display the count of Spark, Comments, and Share.
**Show Links**: Enable this option if you want to make linkouts visible.
**Position**: Select where you want to display the link. From Outside or Overlay
**Autoplay Video**: Enable this option to autoplay the video
**Group Video**: Enable this option to replay the video until any other video is played
### Step 6: Generate Embed Code
After configuring all settings, click on “View Embed Code.” A slider will open from the right, providing you with the code.
### Step 7: Integrate Into Your Website
Copy the generated code and paste it into your website where you want the content to appear.
## Managing Your Embeds
Once you create an embed, it will be listed in the Embed List. This section provides a central location where you can easily access and manage all of your existing embeds.
Within the Embed List, you can monitor key performance metrics to gain insights into how your content is performing. These metrics include:
* **Video Impressions**
* **Unique Users**
* **Embed Impressions**
* **Video Watched Duration**
* **Video Completion Rate**
You can also use filtering options to view specific data segments, allowing you to focus on particular aspects of your embed’s performance.
### Edit Embed
To make changes to an embed, click the Edit button. This allows you to update settings, customize styles, or adjust content as needed.
### Delete Embed
If you need to remove an embed, simply click the Delete button. This will permanently remove the embed from both your list and your website.
## Front Demonstration
### Mobile View
#### Carousel
Carousel style displays videos in a horizontal, swipeable layout for easy browsing. You can easily embed such videos in your Android or iOS platforms.
# SDK For Brands
Source: https://resources.begenuin.com/developers/guides/ios_sdk_for_brands
When you’re looking to enhance your brand’s mobile experience with community building, the [SDK](https://resources.begenuin.com/developers/sdk-docs/ios_sdk) for Brands is your go-to toolkit. It seamlessly connects your existing infrastructure with mobile apps, enabling smooth integration of community building, video management, and custom avatar creation.
## Key Features
* **Community Integration**: Integrate brand-specific communities within your app, allowing users to join, create, and manage communities while maintaining brand consistency.
* **Video Content Management**: Enable users to create, upload, and share videos, with auto-generation features for easy content creation.
* **Auto-Create Features**: Quickly set up brand-aligned communities and automate video generation, streamlining user experience.
## Getting Started
### Setup and Installation
The first step in utilizing the [SDK](https://resources.begenuin.com/developers/sdk-docs/ios_sdk) for Brands is to integrate it into your mobile application. The SDK comes with detailed documentation and easy-to-follow setup guides to ensure smooth implementation.
### User Login and Authentication:
The SDK supports secure user authentication through OTP (One-Time Password). This ensures that all user interactions within the app are secure and in line with your brand’s standards.
### Join as a Creator
Empower your brand by becoming a Creator. This role allows you to create, manage, and organize communities on the platform, ensuring that everything aligns with your brand’s standards.
### Create Your First Group
Start by creating your first Group to organize videos around specific topics. A Group is a category or group of videos, like "Quick Meals" or "Desserts," that helps keep content organized and makes it easier for community members to find what they're interested in.
#### Auto Create Group
Steps:
1. Open the Community.
2. Tap "Create a Group".
3. Choose "Auto Create Group".
4. Select a Topic.
5. Add Members.
6. Choose who can see the group: Everyone or Members Only.
7. Decide who can post in the group: All Community Members or Group Members Only.
The Group name and description will be automatically generated. You can update these details by tapping “Retry With Prompt” and entering a new prompt.
After entering the details, you'll need to [record a post](https://resources.begenuin.com/developers/guides/ios_sdk_for_brands#record-your-first-video-for-loop) for the Group to complete the creation process.
#### Create Group Manually
Steps:
1. Open the Community.
2. Tap "Create a Group".
3. Insert the Group Name and Description
4. Choose who can see the group: Everyone or Members Only.
5. Decide who can post in the group: All Community Members or Members Only.
6. Add Members
After entering the details, you'll need to [record a post](https://resources.begenuin.com/developers/guides/ios_sdk_for_brands#record-your-first-video-for-loop) for the Group to complete the creation process.
### Record Your First Video for Group
Once a Group is set up, users can start sharing content right away.
#### Manually Create Video
1. Tap "Record a Post."
2. Upload a video from your gallery or record a new one.
3. Add a caption to your post.
4. Optionally, add a link to direct viewers to a webpage.
5. Tap "Post" to publish the video and create the Group.
#### Auto Create Video
1. Tap "Record a Post."
2. On the Video Recorder screen, tap "Auto Create."
3. Select a keyword.
4. Choose an Avatar.
5. Tap "Generate
Your AI-generated video will be processed, and you'll receive a notification when it's ready. Tap the notification to review the video, and you'll have two options:
* **Regenerate**: Opens a prompt window where you can input a new prompt to regenerate the video.
* **Next**: Post the video on the platform
### Video Editor
Our in-built video editor lets you easily add clips, trim them, and enhance your video with stickers and text.
Steps:
1. Open the Video Recorder screen.
2. Record a new clip or upload one from your gallery.
3. Tap the red tick mark to preview the video after uploading.
4. On the left side, you'll see icons for Stickers, Text, and Trim.
5. Use these icons to add stickers, insert text, or trim your video.
6. Once editing is complete, tap "Next" to [post the video](https://docs.google.com/document/d/1VX8zLPrBzFjvmq-pFXgoX4QrfFIYwUKTvcdy-tQ2bIc/edit#heading=h.c6nrlia8yqmo).
## Best Practices
### Brand Consistency
Ensure that all SDK integrations are aligned with your brand’s visual and functional standards. This includes customizing community names, video descriptions, and avatars to reflect your brand's identity.
### User Engagement
Utilize the SDK's capabilities to foster deeper user engagement. By offering tools for easy content creation and community management, you can enhance the user experience and build a stronger connection with your audience.
### Continuous Monitoring
Regularly monitor the performance of the SDK integrations within your app. Use analytics to track user interactions and optimize the features to better serve your brand's goals.
## Conclusion
The [SDK](https://resources.begenuin.com/developers/sdk-docs/ios_sdk) for Brands offers a powerful solution to integrate your brand into a mobile experience seamlessly. By leveraging its community management, video content creation, and custom avatar features, you can build a more engaging and personalized app experience for your users. Whether you're setting up a new community, managing video content, or personalizing user avatars, this SDK is designed to enhance your brand's presence.
# Upload
Source: https://resources.begenuin.com/developers/guides/upload
Do you have content in bulk? Upload the short form content to your platform all at once by using our Engage Functionality.
## Upload
Navigate to **Engage > Import Videos > Uploads**, you can upload the videos to post it.
To upload the Video you can, drag and drop the videos or upload it from the **Computer**, **Google Drive**, **Dropbox**, and **S3 Bucket**.
Note: The duration of video shall be less than 300 seconds and up to 2 GB in size. Supported formats to upload files are mp4, mov, avi, wmv, mkv, webm.
**Select Import Destination**: Choose the appropriate Community or Group where you want to import the video.
Once you have uploaded the video you can apply the below **additional setting** to it. These settings will help you generate engaging content and add it to your community.
## Additional Settings
After uploading, you can apply the following settings to upgrade your video experience.

### Add Title
Enable the **Add Title** feature to generate a title based on the video content.
### Add Caption
Enable the **Add Caption** feature to automatically generate captions for your video clips.
### Add Background Music
Enable this option to apply background music to uploaded video.
### Add Description
Enable this option to automatically generate a description for your video upto 2000 characters. Each clip will include a relevant description, making it easier for viewers to understand the context without additional manual input.
## Caption Style
* ### Best Fit
This option automatically adjusts captions for optimal readability and placement, ensuring they blend naturally with the video.
* ### Custom
Choose from multiple predefined caption styles to match your video's aesthetic. This allows you to select a preferred font, size, and color.
### Add Smart Crop
Smart crop features crop out the person from the video and displays in such a way that more focus is on the person who is talking. Below is an example of it.
### Clickbait Thumbnail
If you want to generate the thumbnail with text then enable this feature. Thumbnail would be the best frame fetched from the video and the text will be applied which will be related to the video. Here is an example of it.
You selected the additional settings? Great! Now its time to import the videos. Once you click the **Import** button, the videos will be imported to the ecosystem.
## Data Logs
You can see the import status from the **Data Logs > Uploads** and other details like **Name**, **Date**, **Import Status** and **Posted** (Yes/No).
You can also filter the data based on the **Dates**, **Status**, and **Source**.
The **Completed** status, depicts that the videos are successfully imported and you can **Approve** it to post on your platform.
## Activity
In the Activity section, you can see how many videos are being **Processed**, **Awaiting Approval**, **Approved**, and **Rejected**.
You can filter the data from **Social Import**, **Uploads**, or **Clipit** or you can directly view the **Pending** to review, **Reviewed**, or **All** Videos.
### Approve/Reject Video
Based on the content of Video, you can view the suggested **Community** and **Group** name. Within the Group name your uploaded video will be visible. You can select the video and **Approve** it to post it or you can **Reject** it if you don’t like the video.
Below is an example of **Approved** and **Rejected** video.
### Move
You can also move the video to another community and group, if the current doesn’t seem the correct community or group.
### View
By clicking on the **View** button, you can see the video, along with its details and **Approve/Reject** options.
### Change Community/Group Name
You don’t like the generated community/group name? You can change it as per your requirement by clicking this edit icon.

Slider from the right side will open up where you can change the details as per your requirement.

# Big Query
Source: https://resources.begenuin.com/developers/integrations/bigquery
Big query offers access to structured **data storage**, **analytics** which is cost effective and widely used by multiple business. You can easily connect your BigQuery account to the **BCC (Brand Control Center)** and receive the [Zero party data](https://resources.begenuin.com/faqs/zero_party_data). Firstly follow the below steps to build the BigQuery connection with the Google Cloud account.
## Big Query
**Step 1**: Open your google cloud account, create a service account and click on **Edit** permission.
**Step 2**: Assign the role.
* **2.1**: Role = BigQuery Data Editor
**Step 3**: Set the condition as shown in the image.
* **3.1**: Set **Condition 1** as **Service** > **is** > **bigquery.googleapis.com**
* **3.2**: Set **Condition 2** as **Name** > **Starts with** > `projects//`
Following are the steps to connect your **BigQuery** account with BCC (Brand Control Center).
## Step 1: Login to BCC

## Step 2: Navigate to **Settings** > **Data Sources** > **Big Query**
## Step 3: **Select Account type** (**User** or **Service**),
### For User
Insert the **Dataset ID** (`project_name.dataset_name`) and set the **frequency** (**Daily**, **Weekly**, **Monthly**) to send the Data. **Sign in with Google** to connect the BigQuery account.
### For Service
**Note:** If you have selected the **Service** as an **Account Type** then you have to upload the [JSON authentication file](https://support.google.com/a/answer/7378726?hl=en#:~:text=the%20service%20account-,Click%20APIs%20&%20Services,Click%20Close) along with dataset name
After uploading all the details click on the **Connect** button to connect the **BigQuery** account.
## Connection
Once the connection is successfully built then a table named “**genuin\_data**” will be created under your dataset.
All of the data will be passed based on the below structure.
## Disconnection
Once the **BigQuery** account is connected then you can also **Disconnect** it.
Confirm the **Disconnection** request as shown in the below screenshot.
Once the connection is successfully disconnected then a toast message will be visible.
Now the data will not be sent further although the past data will remain the same.
# Post video
Source: https://resources.begenuin.com/developers/post_video
The **Post Video** API allows you to upload and share videos directly within a Loop.
**URL** : `/api/thirdparty/conversation/reply`
**Method** : `POST`
**Auth required** : YES
**Mandatory Fields**: chat\_id, aspect\_ratio, duration, link, resolution, size, video\_name, thumbnail\_name
**Note** : You need to Authorize [gn-access-token](https://resources.begenuin.com/developers/authentication) as `Bearer Token` to run the API.
# Request Body
```json theme={null}
{
"aspect_ratio": "16:9",
"duration": "8",
"link": "",
"resolution": "688x1220",
"size": "5",
"chat_id": "1a14b9e2-9552-48d5-b1e3-a1ba237891cf",
"video_name": "917016535860_15954965.mp4",
"thumbnail_name": "917016535860_15954965.jpg",
"description_text": "hi this is @hg and i like community abc",
"description_data": "[\"hithisis\",{\"user_id\":\"355c0856-9d99-4286-a3e0-fc5164b77861\"},\"andilikecommunity\",{\"community_id\":\"fe3bdd3b-1fcb-44f3-a7ac-15b59796b6f9\"}]",
"questions": [
"1305faddc8000a5b",
"1305f96cac800a5a"
],
"is_ai_generated": false,
"message_id": "d282b66a-9c3d-4712-b0d5-1c698d923dec",
"video_path": "trends_videos/2024/5/6/genuin",
"thumbnail_path": "trends_thumbnail/2024/5/6/genuin",
"is_ai_generated_video": true,
"is_ai_generated_thumbnail": true
}
```
## Success Response
**Condition**: If Everything is okay and video is posted.
**Code**: `200`
**Content**
```json theme={null}
{
"code": 200,
"message": "Reply Sent Successfully",
"data": {
"chat_id": "1a14b9e2-9552-48d5-b1e3-a1ba237891cf",
"type": 4,
"no_of_views": 0,
"share_url": "https://app.qa.begenuin.com/l/11d88992ba811475",
"is_offline": false,
"settings": {
"discoverable": true
},
"group": {
"group_id": "9f71fbc4-7a2d-4969-a812-73aa4043a1d8",
"group_name": "debug aerospike",
"group_description": "#red",
"color_code": "#8DC6E8",
"text_color_code": "#1B8DD1",
"dp": "http://media.qa.begenuin.com/uploads/profile_images/rt/123.png",
"dp_s": "http://media.qa.begenuin.com/uploads/profile_images/rt/s/123.png",
"dp_m": "http://media.qa.begenuin.com/uploads/profile_images/rt/m/123.png",
"dp_l": "http://media.qa.begenuin.com/uploads/profile_images/rt/l/123.png",
"no_of_views": 0,
"no_of_videos": 0,
"no_of_members": 0,
"no_of_subscribers": 0
},
"chats": [
{
"owner": {
"member_id": "355c0856-9d99-4286-a3e0-fc5164b77861",
"name": "Hiren Ganatra",
"nickname": "hg",
"bio": "🤐🤨😐😑😶😏😒🙄😷😴🤤😪😔😌🤥😬🤒🤕🤢🤮🤧🥵🥶🥴😵🤯🤠🥳🥸😎🤓🧐😳😲😯😮☹🙁😟😕😤😡😠🤬😈👿🤖👾👽👺👻👹🤡💩💯💯💯💤💤💤💤🤳🤳🏿🤳🏿🦾🦿👅👅👅👅👅👅👅",
"is_avatar": true,
"profile_image": "cow_face"
},
"user_id": "355c0856-9d99-4286-a3e0-fc5164b77861",
"thumbnail_url": "http://media.begenuin.com/uploads/thumbnails/917016535860_15954966.jpg",
"thumbnail_url_s": "",
"thumbnail_url_l": "",
"video_url": "http://media.begenuin.com/temp_video/917016535860_15954966.mp4",
"link": "",
"duration": "8",
"size": "5",
"aspect_ratio": "16:9",
"resolution": "688x1220",
"conversation_id": "a5006e51-8950-4e1f-9b9a-65714720b0a6",
"conversation_at": 1644237352000,
"is_read": true,
"is_reply": false,
"questions": [
{
"question_id": "1305f96cac800a5a",
"question": "What would you do with your life if money were no object?",
"date": 1640683621000,
"share_url": "https://app.qa.begenuin.com/q/1305f96cac800a5a"
}
],
"no_of_views": 0,
"no_of_comments": 0,
"share_url": "https://app.qa.begenuin.com/v/11d88992ba811475?l=136fe23cf7001400"
}
]
}
}
```
**Note**: The `conversation_id` provides the unique identifier for a video, and the URL can be found in the `share_url` at the `conversation_id` level, such as `https://app.qa.begenuin.com/v/11d88992ba811475?l=136fe23cf7001400` for the video.
## Bad Request
**Condition**: If the request contains errors or invalid data, resulting in video not posted.
**Code**: `400`
**Content**
```
{}
```
## Internal Server Error
**Condition**: If an unexpected issue occurs on the server, an `Internal Server Error` is returned.
**Code**: `500`
**Content**
```json theme={null}
{
"code": "5057",
"message": "You have already replied to this video.",
"data": {}
}
```
# Android SDK
Source: https://resources.begenuin.com/developers/sdk-docs/android_sdk
Genuin Android SDK comprises features such as brand feed, communities, and groups.
## Requirements
| Platform | Minimum SDK Version | Language | Supported Orientations | Supported Destinations |
| -------- | ------------------- | ----------- | ---------------------- | ---------------------- |
| Android | 24 | Java/Kotlin | Portrait | Mobile |
## Installation
**Note**: Currently minimum SDK version is 24 but if you want to use our SDK in version below 24, use the below code snippet in the App level manifest file.
```kotlin theme={null}
```
**Warning**: If you use the above code then possible it may lead to the functionality failure in some cases.
**1. Add repo details in project level gradle**
```kotlin Kotlin-settings.gradle.kts theme={null}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
jcenter()
maven {
setUrl("https://jitpack.io")
}
maven {
setUrl("https://genuin-media.s3.us-east-1.amazonaws.com/android_assets/")
}
}
}
```
```java Groovy-build.gradle theme={null}
allprojects {
repositories {
google()
mavenCentral()
jcenter()
maven {
setUrl("https://jitpack.io")
}
maven {
setUrl("https://genuin-media.s3.us-east-1.amazonaws.com/android_assets/")
}
}
}
```
**2. Add dependency in app level gradle**
```kotlin Kotlin-build.gradle.kts theme={null}
implementation("org.bitbucket.genuindev:genuin_android_sdk:1.1.17.3@aar"){
isTransitive=true
}
```
```java Groovy-build.gradle theme={null}
implementation('org.bitbucket.genuindev:genuin_android_sdk:1.1.17.3@aar') {
transitive = true
}
```
**3. Add permissions to AndroidManifest.xml**
Mandatory Permissions
```kotlin AndroidManifest.xml theme={null}
```
Following permissions are optional and can be added in `AndroidManifest.xml` file as per feature requirements:
* To allow user to **Create Video Content**, **Camera** and **Mic** permissions are needed:
```kotlin AndroidManifest.xml theme={null}
```
* To allow user to **Upload Content** from their gallery
```kotlin AndroidManifest.xml theme={null}
//API level > 32
//API level <= 32
```
* To allow user to add their **Contacts as Members** in **Communities** and **Groups**:
```kotlin AndroidManifest.xml theme={null}
```
* To allow user to receive **Push Notifications**:
```kotlin AndroidManifest.xml theme={null}
```
* To allow creation of **AI Powered Communities** based on the **User Location**:
```kotlin AndroidManifest.xml theme={null}
```
**4. Initialize SDK**
```kotlin YourApplication.kt theme={null}
class YourApplication : Application() {
override fun onCreate() {
// For Prod Environment
GenuinSDK.initSDK(this, "YOUR_API_KEY")
// For QA Environment
GenuinSDK.initSDK(this, "YOUR_API_KEY", genuinEnv = GenuinEnv.QA)
}
}
```
```kotlin YourActivity.kt theme={null}
class YourActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// For Prod Environment
GenuinSDK.initSDK(application, "YOUR_API_KEY")
// For QA Environment
GenuinSDK.initSDK(application, "YOUR_API_KEY", genuinEnv = GenuinEnv.QA)
}
}
```
**5. Load SDK in seperate activity**
```kotlin theme={null}
GenuinSDK.loadSDK(context)
```
**6. Load SDK in your custom activity**
Put below code in `activity_custom.xml` file
```Kotlin activity_custom.xml theme={null}
```
Put below code in `CustomActivity.kt` file
```Kotlin CustomActivity.kt theme={null}
import com.begenuin.begenuin.FeedFragment
class CustomActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_custom)
val genuinFeedFragment = FeedFragment()
supportFragmentManager.beginTransaction()
.add(R.id.frameLayout, genuinFeedFragment)
.addToBackStack("feedFragment").commit()
}
}
```
**Note**: In your custom activity, set soft input mode to `adjustPan` for better performance
```kotlin AndroidManifest.xml theme={null}
android:windowSoftInputMode="adjustPan"
```
**7. Load SDK with bottom navigation and fragment**
Add below code in `res/navigation/mobile_navigation.xml`
```xml theme={null}
```
Add below code in your activity
```kotlin ViewPager2 theme={null}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setSupportActionBar(Toolbar(this))
initViewPager()
val navView: BottomNavigationView = binding.navView
navView.setOnItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_community -> {
binding.viewPager.setCurrentItem(1, false)
true
}
else -> false
}
}
}
private fun initViewPager() {
val myPagerAdapter = MyPagerAdapter(this)
binding.viewPager.adapter = myPagerAdapter
}
class MyPagerAdapter(fragmentActivity: FragmentActivity) :
FragmentStateAdapter(fragmentActivity) {
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> FeedFragment()
else -> FeedFragment()
}
}
override fun getItemCount(): Int {
return NUM_PAGES
}
companion object {
private const val NUM_PAGES = 1
}
}
```
```kotlin NavHost theme={null}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setSupportActionBar(Toolbar(this))
val navView: BottomNavigationView = binding.navView
val navController =
findNavController(R.id.nav_host_fragment_activity_bottom_tab_with_nav_host)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_community
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
```
**8. Want to override our default loader.**
We are using lottie animation for our loader. You can put your custom lottie animation loader with the name `loader_mix.json` in the `res/raw` folder. Make sure you use the same name as provided.
**Note**: In AndroidManifest.xml, in the `` tag, set `android:allowBackup="false"`
## Monetization
* To enable the **Monetization** add the below code:
```kotlin AndroidManifest.xml theme={null}
```
**Need to declare in Google play console that your app is using Advertising ID**
Steps:
* **Log in** to your Google Play Console.
* **Select the app** you are working on.
* Go to **Policy** and **programs > App content**.
* Find the **Advertising ID** section and click on **Manage**.
* Select "**yes**" that your app is using Advertising ID
* After answering the questions, submit your declaration.
## Embed
**Note**: Make sure you have followed the [First 3 installation steps](https://resources.begenuin.com/developers/sdk-docs/android_sdk#installation) in order to implement the Carousel Embed
### Carousel Embed
Refer to [Carousel View](https://resources.begenuin.com/developers/guides/embed#mobile-view) in mobile.
**1. Load Carousel Embed with XML**
```xml activity_embed.xml theme={null}
```
**Note**: Carousel Container height must be fixed or match\_parent. It can not be wrap\_content else carousel embed will not appear.
```kotlin EmbedActivity.kt (With SSO) theme={null}
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
carouselEmbedView.apply {
setEmbedParams(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false
)
setActivity(activityContext)
setSSOToken("YOUR_SSO_TOKEN")
setParams(params) // User specific params
setAspectRatio(CarouselTileAspectRatio.RATIO_4_5)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setContextualParams(contextualParams) // Contextual params
load()
}
```
```kotlin EmbedActivity.kt (Without SSO) theme={null}
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
carouselEmbedView.apply {
setEmbedParams(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false
)
setActivity(activityContext)
setAspectRatio(CarouselTileAspectRatio.RATIO_4_5)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setContextualParams(contextualParams) // Contextual params
load()
}
```
**2. Load Carousel Embed Programmatically**
```xml activity_embed.xml theme={null}
```
**Note**: Carousel Container height must be fixed or match\_parent. It can not be wrap\_content else carousel embed will not appear.
```kotlin EmbedActivity.kt (With SSO) theme={null}
val carouselEmbedView = CarouselEmbedView(context)
llCarouselContainer.addView(carouselEmbedView)
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
carouselEmbedView.apply {
setEmbedParams(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false
)
setActivity(activityContext)
setAspectRatio(CarouselTileAspectRatio.RATIO_4_5)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setSSOToken("YOUR_SSO_TOKEN")
setParams(params) // User specific params
setContextualParams(contextualParams) // Contextual params
load()
}
```
```kotlin EmbedActivity.kt (Without SSO) theme={null}
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
val carouselEmbedView = CarouselEmbedView(context)
llCarouselContainer.addView(carouselEmbedView)
carouselEmbedView.apply {
setEmbedParams(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false
)
setActivity(activityContext)
setAspectRatio(CarouselTileAspectRatio.RATIO_4_5)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setContextualParams(contextualParams) // Contextual params
load()
}
```
#### Vertical Carousel Embed
To implement vertical carousel, you can use `setScrollDirection(CarouselScrollDirection.VERTICAL)` and other configurations will be same as above.
```kotlin VerticalEmbedActivity.kt theme={null}
// Example Code Snippet
carouselEmbedView.apply {
setEmbedParams(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
)
setActivity(activityContext)
setScrollDirection(CarouselScrollDirection.VERTICAL)
setAspectRatio(CarouselTileAspectRatio.RATIO_4_5)
load()
}
```
**Note**: To initialise the Embed you need to add your activity context `(setActivity(activityContext))` in which you want the embed. To auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN"`(setSSOToken("YOUR_SSO_TOKEN"))` in order to implement Embed with SSO in your app.
To configure the `EmbedParams` based on your need you can pass the below values.
1. **embedId** = The Embed Id that you want to load.
2. **uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
3. **interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
4. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
**Note**: For using `isDirectDeepLinkEnabled` parameter, you must have [white labelled your domain](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community) first and also integrated the [Handling deep link](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handling-deep-link) part in your main app in which you want to redirect this video to.
5. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
**Add user specific parameters (Optional)**
a. **name** - This is an optional string parameter. Pass this parameter for `signup/login`.
b. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
c. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
d. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
e. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
**Add contextual parameters (Optional)**
a. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
b. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
c. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
**Add design configurations (Optional)**
a. **interTileSpacing** - spacing between the carousel's view items. It's default value is `8dp`
b. **carouselInset** - edge insets for carousel's view. It's default value is `top: 8dp, left: 16dp, bottom: 0dp, right: 16dp`
c. **scrollDirection** - direction of carousel scroll. It's default value is `CarouselScrollDirection.HORIZONTAL`
d. **aspectRatio** - define aspect ratio of carousel's view items. It's default value is `CarouselTileAspectRatio.RATIO_9_16`
e. **tileCornerRadius** - cornerRadius for the carousel's view items. It's default value is `8dp`
**3. Manage carousel videos auto-play**
```kotlin EmbedActivity.kt theme={null}
override fun onResume() {
super.onResume()
carouselEmbedView.resumeVideoAutoPlay()
}
override fun onPause() {
carouselEmbedView.pauseVideoAutoPlay()
super.onPause()
}
```
### Full Screen Embed
Put below code in `activity_full_embed.xml` file
```Kotlin activity_full_embed.xml theme={null}
```
Put below code in `FullEmbedActivity.kt` file
```Kotlin FullEmbedActivity.kt theme={null}
import com.begenuin.sdk.ui.fragment.FeedEmbedFragment
class FullEmbedActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_full_embed)
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
val feedEmbedFragment = FeedEmbedFragment.newInstance(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false,
ssoToken = "YOUR_SSO_TOKEN",
params = params // User specific params,
contextualParams = contextualParams
)
feedEmbedFragment.let {
supportFragmentManager.beginTransaction()
.add(R.id.frameLayout, it)
.addToBackStack("EmbedFullFeed").commit()
}
}
}
```
We need to pass below arguments in order to cofigure `FullScreenEmbed`.
1. **embedId** = The Embed Id that you want to load.
2. **uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
3. **interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
4. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
**Note**: For using `isDirectDeepLinkEnabled` parameter, you must have [white labelled your domain](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community) first and also integrated the [Handling deep link](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handling-deep-link) part in your main app in which you want to redirect this video to.
5. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
6. **ssoToken**: This is an optional parameter. To auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN" in order to implement Embed with SSO in your app.
**Add user specific parameters (Optional)**
a. **name** - This is an optional string parameter. Pass this parameter for `signup/login`.
b. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
c. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
d. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
e. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
**Add contextual parameters (Optional)**
a. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
b. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
c. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
### Standard Wall Embed
Put below code in `activity_standard_wall_embed.xml` file
```Kotlin activity_standard_wall_embed.xml theme={null}
```
Put below code in `StandardWallEmbedActivity.kt` file
```Kotlin StandardWallEmbedActivity.kt theme={null}
import com.begenuin.sdk.ui.fragment.FeedEmbedFragment
class StandardWallEmbedActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_standard_wall_embed)
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
val feedEmbedFragment = FeedEmbedFragment.newInstance(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false,
ssoToken = "YOUR_SSO_TOKEN",
params = params, // User specific params
contextualParams = contextualParams // Contextual params
)
feedEmbedFragment.let {
supportFragmentManager.beginTransaction()
.add(R.id.frameLayout, it)
.addToBackStack("EmbedStandardWallFeed").commit()
}
}
}
```
We need to pass below arguments in order to cofigure `StandardWallEmbed`.
1. **embedId** = The Embed Id that you want to load.
2. **uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
3. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
4. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
**Note**: For using `isDirectDeepLinkEnabled` parameter, you must have [white labelled your domain](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community) first and also integrated the [Handling deep link](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handling-deep-link) part in your main app in which you want to redirect this video to.
5. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
6. **ssoToken**: This is an optional parameter. To auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN" in order to implement Embed with SSO in your app.
**Add user specific parameters (Optional)**
a. **name** - This is an optional string parameter. Pass this parameter for `signup/login`.
b. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
c. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
d. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
e. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
**Add contextual parameters (Optional)**
a. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
b. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
c. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
## Handle Login : via AutoLogin Approach
To Auto Login in the SDK, You need to call below method, whenever user is log in to your application.
**Note**: You don't need to call the below method if you have implemented the Embed With SSO already.
```kotlin YourClass.kt theme={null}
GenuinSDK.ssoLogin(context = "YOUR_CONTEXT", ssoToken = "YOUR_SSO_TOKEN")
```
### Optional Parameters
Below are the optional parameters you can add with the function:
```kotlin YourActivity.kt theme={null}
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
GenuinSDK.ssoLogin(
context = "YOUR_CONTEXT",
ssoToken = "YOUR_SSO_TOKEN",
params = params //This is optional
)
```
**Add user specific parameters (Optional)**
1. **name** - This is an optional string parameter. Pass this parameter for '`signup/login`'.
2. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
3. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
4. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
5. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
### Optional Callback
```kotlin YourClass.kt theme={null}
GenuinSDK.ssoLogin(
context = "YOUR_CONTEXT",
ssoToken = "YOUR_SSO_TOKEN",
params = "YOUR_OPTIONAL_PARAMS",
onComplete = {
isSuccess: Boolean ->
//Manage callback for Login Completion
}
)
```
```kotlin YourClass.java theme={null}
GenuinSDK.INSTANCE.ssoLogin(
"CONTEXT",
"SSO-TOKEN",
"OPTIONAL-PARAMETERS",
(isSuccess) -> {
//Manage callback for Login Completion
return Unit.INSTANCE;
}
);
```
## Custom Login
If you want to handle login process as per your requirement then follow the below steps:
```kotlin YourActivity.kt theme={null}
GenuinSDK.registerInterface(object : GenuinInterface {
override fun onLogin(context: Activity) {
/*
This callback will be triggered when user attempts to login
within one of the Genuin embeds. Application login process
should be initiated here.
When your application's auth process is successfully completed,
call GenuinSDK.ssoLogin(context, "ssoToken") to automatically
manage SDK login.
*/
}
})
```
## Handle Logout : via AutoLogin Approach
Whenever user logs out from your application call the below method.
GenuinSDK.ssoLogout(context = "YOUR\_CONTEXT")
### Optional Callback
```kotlin YourClass.kt theme={null}
GenuinSDK.ssoLogout(
context = "YOUR_CONTEXT",
onComplete = {
isSuccess: Boolean ->
//Manage callback for Logout Completion
}
)
```
```kotlin YourClass.java theme={null}
GenuinSDK.INSTANCE.ssoLogout(
"CONTEXT",
(isSuccess) -> {
//Manage callback for Logout Completion
return Unit.INSTANCE;
}
);
```
## Handling Deep Link
**Note**: Make sure you have followed the [First 3 installation steps](https://resources.begenuin.com/developers/sdk-docs/android_sdk#installation) in order to handle the deep link.
**Prerequisite**:
1. Make sure you have white labelled your community by following these [steps](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community).
2. Follow the steps given in the below URL to integrate deeplink in your app
[https://developer.android.com/studio/write/app-link-indexing](https://developer.android.com/studio/write/app-link-indexing)
**Note** : Here host will be your "YOUR\_WHITE-LABELLED\_DOMAIN"
3. After completing deeplink setup, your `assetlinks.json` file should look like below
```kotlin assetlinks.json theme={null}
[{"target":{"package_name":"YOUR_PACKAGE_NAME","sha256_cert_fingerprints":["YOUR_KEYSTORE'S_SHA256_FINGERPRINTS"],"namespace":"android_app"},"relation":["delegate_permission/common.handle_all_urls"]}]
```
4. Host `assetlinks.json` file on the white labeled domain at `https://YOUR_WHITE-LABELLED_DOMAIN/.well-known/assetlinks.json`
**To Handle Our Deep Link In Your App**
You can call the below method immediately after receiving deeplink or you can wait until your app's home screen is loaded.
```kotlin YourCustomActivity.kt theme={null}
GenuinSDK.handleDeepLink(context = "YOUR_CONTEXT", intent = "YOUR_DEEPLINK_ACTIVITY_INTNET")
```
**Note**: Need to call this function everytime your app receives any deeplink. This method will handle deeplink if it is our's otherwise it will ignore that.
## Handling Push Notifications
**Note**: Make sure you have followed the [First 3 installation steps](https://resources.begenuin.com/developers/sdk-docs/android_sdk#installation) in order to handle the push notifications.
**Prerequisite:**
1. Create an app in your firebase using [these steps](https://firebase.google.com/docs/android/setup)
2. Download the `google-services.json` file and add it into your app.
3. Integrate firebase into your app by following [these steps](https://firebase.google.com/docs/cloud-messaging/android/client)
**Get firebase token and register it with Genuin SDK**
```kotlin theme={null}
private fun getFirebaseToken(){
FirebaseMessaging.getInstance().token
.addOnCompleteListener { task: Task ->
if (!task.isSuccessful) {
return@addOnCompleteListener
}
// Get new FCM registration token
val token = task.result
// Register token with Genuin SDK
GenuinSDK.registerFCMToken("YOUR_CONTEXT", token)
}
}
```
**Handle foreground notifications (When your app is in foreground)**
```kotlin MyFirebaseMessagingService.kt theme={null}
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
val data: Map = remoteMessage.getData()
if (GenuinSDK.willHandleForegroundNotification(data)) {
val message = remoteMessage.notification?.body ?: ""
GenuinSDK.handleForegroundNotifications(
context = this,
data = data,
message = message,
smallNotificationIcon = R.drawable.ic_small_notifications // Your app's notification small icon
)
} else {
// Handle other push notifications for your app
}
}
/**
* There are two scenarios when onNewToken is called:
* 1) When a new token is generated on initial app startup
* 2) Whenever an existing token is changed
* Under #2, there are three scenarios when the existing token is changed:
* A) App is restored to a new device
* B) User uninstalls/reinstall the app
* C) User clears app data
*/
override fun onNewToken(s: String) {
super.onNewToken(s)
GenuinSDK.registerFCMToken(this, s)
}
}
```
**Note**: `GenuinSDK.willHandleForegroundNotification(data: Map)` function will check whether GenuinSDK will handle the given notification or not when app is in foreground.
**Handle notifications while app is running in background or closed**
* Whenever user clicks on notifications, you will get the notification payload in your launcher activity.
```kotlin YourLauncherActivity.kt theme={null}
if (GenuinSDK.willHandleNotification(intent)) {
GenuinSDK.handleBackgroundNotifications(context = "YOUR_CONTEXT", intent)
}
```
**Note**: `GenuinSDK.willHandleNotification(intent: Intent)` function will check whether GenuinSDK will handle the given notification or not.
## What’s next?
Integrate iOS SDK in Your ecosystem.
Integrate Web SDK in your ecosystem.
Integrate React Native SDK in your ecosystem.
## Support
If you need any assistance or have any questions, feel free to email us at [support@begenuin.com](mailto:support@begenuin.com).
# Android SDK 2.0
Source: https://resources.begenuin.com/developers/sdk-docs/android_sdk_2.0
Genuin Android SDK comprises features such as brand feed, communities, and groups.
| SDK | Description | Dependency |
| ------ | ------------------------------------------------------------------------------------------------- | ------------------------- |
| Core | Includes the core functionality of the Genuin Ecosystem: Embeds and User authentication. | com.begenuin:core:2.1.2 |
| UI | Additional UI flows like comments, search, deep-links, notifications, group/community detail etc. | com.begenuin:ui:2.1.2 |
| Camera | Camera flows for video content creation. | com.begenuin:camera:2.1.2 |
| AI | Additional flows for AI assisted community/group creation. | com.begenuin:ai:2.1.2 |
## Requirements
| Platform | Minimum SDK Version | Minimum AGP Version | Language | Supported Orientations | Supported Destinations |
| -------- | ------------------- | ------------------- | ----------- | ---------------------- | ---------------------- |
| Android | 24 | 8.6.0 | Java/Kotlin | Portrait | Mobile |
## Installation
**Note**: Currently minimum SDK version is 24 but if you want to use our SDK in version below 24, use the below code snippet in the App level manifest file.
```kotlin In AndroidManifext.xml theme={null}
```
Include the respective begenuin modules used as shown above.
**Warning**: If you use the above code then possible it may lead to the functionality failure in some cases.
**1. Add repo details in project level gradle**
```kotlin Kotlin-settings.gradle.kts theme={null}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
setUrl("https://jitpack.io")
}
}
}
```
```kotlin Groovy-build.gradle theme={null}
allprojects {
repositories {
google()
mavenCentral()
maven {
setUrl("https://jitpack.io")
}
}
}
```
**2. Add dependency in app level gradle**
**a. For core SDK**
```kotlin Kotlin-build.gradle.kts theme={null}
val genuinVersion = "2.1.2"
implementation("com.begenuin:core:$genuinVersion")
```
```kotlin Groovy-build.gradle theme={null}
def genuinVersion = "2.1.2"
implementation "com.begenuin:core:$genuinVersion"
```
**b. For UI SDK**
```kotlin Kotlin-build.gradle.kts theme={null}
val genuinVersion = "2.1.2"
implementation("com.begenuin:core:$genuinVersion")
implementation("com.begenuin:ui:$genuinVersion")
```
```kotlin Groovy-build.gradle theme={null}
def genuinVersion = "2.1.2"
implementation "com.begenuin:core:$genuinVersion"
implementation "com.begenuin:ui:$genuinVersion"
```
**c. For Camera SDK**
```kotlin Kotlin-build.gradle.kts theme={null}
val genuinVersion = "2.1.2"
implementation("com.begenuin:core:$genuinVersion")
implementation("com.begenuin:ui:$genuinVersion")
implementation("com.begenuin:camera:$genuinVersion")
```
```kotlin Groovy-build.gradle theme={null}
def genuinVersion = "2.1.2"
implementation "com.begenuin:core:$genuinVersion"
implementation "com.begenuin:ui:$genuinVersion"
implementation "com.begenuin:camera:$genuinVersion"
```
**d. For AI SDK**
```kotlin Kotlin-build.gradle.kts theme={null}
val genuinVersion = "2.1.2"
implementation("com.begenuin:core:$genuinVersion")
implementation("com.begenuin:ui:$genuinVersion")
implementation("com.begenuin:camera:$genuinVersion")
implementation("com.begenuin:ai:$genuinVersion")
```
```kotlin Groovy-build.gradle theme={null}
def genuinVersion = "2.1.2"
implementation "com.begenuin:core:$genuinVersion"
implementation "com.begenuin:ui:$genuinVersion"
implementation "com.begenuin:camera:$genuinVersion"
implementation "com.begenuin:ai:$genuinVersion"
```
Note: All modules must use a consistent version format — 2.1.2.
**Dependency Hierarchy**
The modules follow a linear dependency structure, where each subsequent module depends on the ones before it in the chain:
ai ← camera ← ui ← core
**Module Usage Guidelines**
1. core - Can be used independently. This is the foundational module required by all others.
2. ui - Depends on core. Must include core when using ui.
3. camera - Depends on both core and ui. Must include both when integrating camera.
4. ai - Depends on camera, ui, and core. All three must be included when using ai.
Ensure you maintain the correct order and include all required dependencies when integrating any module beyond core.
**3. Add permissions to AndroidManifest.xml**
Mandatory Permissions
```kotlin AndroidManifest.xml theme={null}
```
Following permissions are optional and can be added in `AndroidManifest.xml` file as per feature requirements:
**a. Permissions for UI SDK**
* To allow user to add their **Contacts as Members** in **Communities** and **Groups**:
```kotlin AndroidManifest.xml theme={null}
```
* To allow user to receive **Push Notifications**:
```kotlin AndroidManifest.xml theme={null}
```
**b. Permissions for Camera SDK**
* To allow user to **Create Video Content**, **Camera** and **Mic** permissions are needed:
```kotlin AndroidManifest.xml theme={null}
```
* To allow user to **Upload Content** from their gallery
```kotlin AndroidManifest.xml theme={null}
//API level > 32
//API level <= 32
```
**c. Permissions for AI SDK**
* To allow creation of **AI Powered Communities** based on the **User Location**:
```kotlin AndroidManifest.xml theme={null}
```
**4. Initialize SDK**
```kotlin YourApplication.kt theme={null}
class YourApplication : Application() {
override fun onCreate() {
// For Prod Environment
GenuinSDK.initSDK(this, "YOUR_API_KEY")
// For QA Environment
GenuinSDK.initSDK(this, "YOUR_API_KEY", genuinEnv = GenuinEnv.QA)
}
}
```
```kotlin YourActivity.kt theme={null}
class YourActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// For Prod Environment
GenuinSDK.initSDK(application, "YOUR_API_KEY")
// For QA Environment
GenuinSDK.initSDK(application, "YOUR_API_KEY", genuinEnv = GenuinEnv.QA)
}
}
```
**5. Want to override our default loader.**
We are using lottie animation for our loader. You can put your custom lottie animation loader with the name `loader_mix.json` in the `res/raw` folder. Make sure you use the same name as provided.
**Note**: In AndroidManifest.xml, in the `` tag, set `android:allowBackup="false"`
## Monetization
* To enable the **Monetization** add the below code:
```kotlin AndroidManifest.xml theme={null}
```
**Need to declare in Google play console that your app is using Advertising ID**
Steps:
* **Log in** to your Google Play Console.
* **Select the app** you are working on.
* Go to **Policy** and **programs > App content**.
* Find the **Advertising ID** section and click on **Manage**.
* Select "**yes**" that your app is using Advertising ID
* After answering the questions, submit your declaration.
## Embed in Kotlin
**Note**: Make sure you have followed the [First 3 installation steps](https://resources.begenuin.com/developers/sdk-docs/android_sdk#installation) in order to implement the Carousel Embed
### Embed
Refer to [Carousel View](https://resources.begenuin.com/developers/guides/embed#mobile-view) in mobile.
**1. Load Carousel Embed with XML**
```xml activity_embed.xml theme={null}
```
**Note**: Carousel Container height must be fixed or match\_parent. It can not be wrap\_content else carousel embed will not appear.
```kotlin EmbedActivity.kt (With SSO) theme={null}
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
genuinEmbedView.apply {
setEmbedParams(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false
)
setActivity(activityContext)
setSSOToken("YOUR_SSO_TOKEN")
setParams(params) // User specific params
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setContextualParams(contextualParams) // Contextual params
load()
}
```
```kotlin EmbedActivity.kt (Without SSO) theme={null}
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
genuinEmbedView.apply {
setEmbedParams(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false
)
setActivity(activityContext)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setContextualParams(contextualParams) // Contextual params
load()
}
```
**2. Load Carousel Embed Programmatically**
```xml activity_embed.xml theme={null}
```
**Note**: Carousel Container height must be fixed or match\_parent. It can not be wrap\_content else carousel embed will not appear.
```kotlin EmbedActivity.kt (With SSO) theme={null}
val genuinEmbedView = GenuinEmbedView(context)
llCarouselContainer.addView(genuinEmbedView)
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
genuinEmbedView.apply {
setEmbedParams(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false
)
setActivity(activityContext)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setSSOToken("YOUR_SSO_TOKEN")
setParams(params) // User specific params
setContextualParams(contextualParams) // Contextual params
load()
}
```
```kotlin EmbedActivity.kt (Without SSO) theme={null}
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
val genuinEmbedView = GenuinEmbedView(context)
llCarouselContainer.addView(genuinEmbedView)
genuinEmbedView.apply {
setEmbedParams(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false
)
setActivity(activityContext)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setContextualParams(contextualParams) // Contextual params
load()
}
```
**Note**: To initialise the Embed you need to add your activity context `(setActivity(activityContext))` in which you want the embed. To auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN"`(setSSOToken("YOUR_SSO_TOKEN"))` in order to implement Embed with SSO in your app.
To configure the `EmbedParams` based on your need you can pass the below values.
1. **embedId** = The Embed Id that you want to load.
2. **uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
3. **interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
4. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
**Note**: For using `isDirectDeepLinkEnabled` parameter, you must have [white labelled your domain](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community) first and also integrated the [Handling deep link](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handling-deep-link) part in your main app in which you want to redirect this video to.
5. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
**Add user specific parameters (Optional)**
a. **name** - This is an optional string parameter. Pass this parameter for `signup/login`.
b. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
c. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
d. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
e. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
**Add contextual parameters (Optional)**
a. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
b. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
c. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
**Add design configurations (Optional)**
a. **interTileSpacing** - spacing between the carousel's view items. It's default value is `8dp`
b. **carouselInset** - edge insets for carousel's view. It's default value is `top: 8dp, left: 16dp, bottom: 0dp, right: 16dp`
c. **tileCornerRadius** - cornerRadius for the carousel's view items. It's default value is `8dp`
**3. Manage carousel videos auto-play**
```kotlin EmbedActivity.kt theme={null}
override fun onResume() {
super.onResume()
genuinEmbedView.play()
}
override fun onPause() {
genuinEmbedView.pause()
super.onPause()
}
override fun onDestroy() {
genuinEmbedView.release()
super.onDestroy()
}
```
**4. Load embed feed asynchronously:**
In order to load embed feeds asynchronously, instead of calling load(), use loadAsync with a callback (as shown). This callback will be triggered once the process of fetching data is complete, along with a boolean flag indicating whether the operation was successful and non-empty feed was retrieved.
```Kotlin activity_full_embed.xml theme={null}
genuinEmbedView.loadAsync {
success ->
if (success) {
binding.genuinEmbedView.visibility = View.VISIBLE
}
}
```
### Full Screen Embed
Put below code in `activity_full_embed.xml` file
```Kotlin activity_full_embed.xml theme={null}
```
Put below code in `FullEmbedActivity.kt` file
```Kotlin FullEmbedActivity.kt theme={null}
import com.begenuin.core.ui.fragment.FeedEmbedFragment
class FullEmbedActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_full_embed)
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
val feedEmbedFragment = FeedEmbedFragment.newInstance(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false,
ssoToken = "YOUR_SSO_TOKEN",
params = params // User specific params,
contextualParams = contextualParams
)
feedEmbedFragment.let {
supportFragmentManager.beginTransaction()
.add(R.id.frameLayout, it)
.addToBackStack("EmbedFullFeed").commit()
}
}
}
```
We need to pass below arguments in order to cofigure `FullScreenEmbed`.
1. **embedId** = The Embed Id that you want to load.
2. **uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
3. **interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
4. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
**Note**: For using `isDirectDeepLinkEnabled` parameter, you must have [white labelled your domain](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community) first and also integrated the [Handling deep link](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handling-deep-link) part in your main app in which you want to redirect this video to.
5. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
6. **ssoToken**: This is an optional parameter. To auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN" in order to implement Embed with SSO in your app.
**Add user specific parameters (Optional)**
a. **name** - This is an optional string parameter. Pass this parameter for `signup/login`.
b. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
c. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
d. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
e. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
**Add contextual parameters (Optional)**
a. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
b. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
c. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
### Standard Wall Embed
Put below code in `activity_standard_wall_embed.xml` file
```Kotlin activity_standard_wall_embed.xml theme={null}
```
Put below code in `StandardWallEmbedActivity.kt` file
```Kotlin StandardWallEmbedActivity.kt theme={null}
import com.begenuin.core.ui.fragment.FeedEmbedFragment
class StandardWallEmbedActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_standard_wall_embed)
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = pageContext
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX)
geoJson.put("long", XXXX.XXX)
contextualParams["geo"] = geoJson.toString()
val feedEmbedFragment = FeedEmbedFragment.newInstance(
embedId = "YOUR_EMBED_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
isShowProfileEnabled = false,
ssoToken = "YOUR_SSO_TOKEN",
params = params, // User specific params
contextualParams = contextualParams // Contextual params
)
feedEmbedFragment.let {
supportFragmentManager.beginTransaction()
.add(R.id.frameLayout, it)
.addToBackStack("EmbedStandardWallFeed").commit()
}
}
}
```
We need to pass below arguments in order to cofigure `StandardWallEmbed`.
1. **embedId** = The Embed Id that you want to load.
2. **uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
3. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
4. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
**Note**: For using `isDirectDeepLinkEnabled` parameter, you must have [white labelled your domain](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community) first and also integrated the [Handling deep link](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handling-deep-link) part in your main app in which you want to redirect this video to.
5. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
6. **ssoToken**: This is an optional parameter. To auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN" in order to implement Embed with SSO in your app.
**Add user specific parameters (Optional)**
a. **name** - This is an optional string parameter. Pass this parameter for `signup/login`.
b. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
c. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
d. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
e. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
**Add contextual parameters (Optional)**
a. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
b. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
c. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
## Embed in Compose
**Note**: Make sure you have followed the [First 3 installation steps](https://resources.begenuin.com/developers/sdk-docs/android_sdk#installation) in order to implement the Carousel Embed
### Carousel Embed
Refer to [Carousel View](https://resources.begenuin.com/developers/guides/embed#mobile-view) in mobile.
```kotlin Basic Embed theme={null}
@Composable
fun CarouselComposeViewWrapper(
modifier: Modifier = Modifier,
embedId: String,
)
{
val context = LocalContext.current
val activity = context as? Activity?: throw IllegalStateException("Context is not an Activity!")
AndroidView(
modifier = modifier,
factory = { viewContext ->
// Creates view
GenuinEmbedView(viewContext)
.setEmbedParams(
embedId,
)
.setActivity(activity)
.load()
}
)
}
```
```kotlin Embed with Customization & SSO theme={null}
@Composable
fun CarouselComposeViewWrapper(
modifier: Modifier = Modifier,
embedId: String,
uniqueId: String = "",
ssoToken: String = "",
isDirectDeepLinkEnabled: Boolean = false,
isShowProfileEnabled: Boolean = false,
interTileSpacing: Int = 24,
tileCornerRadius: Int = 24,
leftInsets: Int = 24,
topInsets: Int = 24,
rightInsets: Int = 24,
bottomInsets: Int = 24,
params: HashMap? = null,
contextualParams: HashMap? = null,
)
{
val context = LocalContext.current
val activity =
context as? Activity ?: throw IllegalStateException("Context is not an Activity!")
AndroidView(
modifier = modifier,
factory = { viewContext ->
// Creates view
GenuinEmbedView(viewContext)
.setEmbedParams(
embedId = embedId,
uniqueId = uniqueId,
isShowProfileEnabled = isShowProfileEnabled,
isDirectDeepLinkEnabled = isDirectDeepLinkEnabled
)
.setActivity(activity)
.setInterTileSpacing(interTileSpacing) // values should be in pixels
.setInsets(
left = leftInsets, // values should be in pixels
top = topInsets, // values should be in pixels
right = rightInsets, // values should be in pixels
bottom = bottomInsets, // values should be in pixels
)
.setTileCornerRadius(tileCornerRadius)// values should be in pixels
.setSSOToken(ssoToken)
.setParams(params)
.setContextualParams(contextualParams)
.load()
}
)
}
```
**Note**: Carousel Container height must be fixed or match\_parent. It can not be wrap\_content else carousel embed will not appear.
Example Usage
```kotlin Basic Embed theme={null}
CarouselComposeViewWrapper(
embedId = "YOUR_EMBED_ID",
modifier = Modifier.fillMaxWidth().height(400.dp) // Height can be dynamic
)
```
```kotlin Embed With Customization and SSO theme={null}
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = "YOUR_CONTEXT_VALUE"
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX) // value in double
geoJson.put("long", XXXX.XXX) // value in double
contextualParams["geo"] = geoJson.toString()
CarouselComposeViewWrapper(
embedId = "YOUR_EMBED_ID",
uniqueId = "UNIQUE_ID",
ssoToken = "YOUR_SSO_TOKEN",
isShowProfileEnabled = false,
isDirectDeepLinkEnabled = false,
tileCornerRadius = 32,
leftInsets = 32,
topInsets = 32,
rightInsets = 32,
bottomInsets = 32,
params = params,
contextualParams = contextualParams,
modifier = Modifier.fillMaxWidth().height(400.dp)
)
```
**Note**: To auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN"`(setSSOToken("YOUR_SSO_TOKEN"))` in order to implement Embed with SSO in your app.
To configure the `EmbedParams` based on your need you can pass the below values.
1. **embedId** = The Embed Id that you want to load.
2. **uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
3. **interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
4. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
**Note**: For using `isDirectDeepLinkEnabled` parameter, you must have [white labelled your domain](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community) first and also integrated the [Handling deep link](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handling-deep-link) part in your main app in which you want to redirect this video to.
5. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
**Add user specific parameters (Optional)**
a. **name** - This is an optional string parameter. Pass this parameter for `signup/login`.
b. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
c. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
d. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
e. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
**Add contextual parameters (Optional)**
a. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
b. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
c. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
**Add design configurations (Optional)**
a. **interTileSpacing** - spacing between the carousel's view items. It's default value is `8dp`
b. **carouselInset** - edge insets for carousel's view. It's default value is `top: 8dp, left: 16dp, bottom: 0dp, right: 16dp`
c. **tileCornerRadius** - cornerRadius for the carousel's view items. It's default value is `8dp`
### Standard Wall Embed
To load standardwall the parent activity must be `FragmentActivity`
```kotlin Basic Embed theme={null}
@Composable
fun StandardWallComposeFragmentWrapper(
modifier: Modifier = Modifier,
embedId: String,
) {
val context = LocalContext.current
val activity = context as? FragmentActivity
?: throw IllegalStateException("Context is not a FragmentActivity")
AndroidView(
factory = { ctx ->
FragmentContainerView(ctx).apply {
id = View.generateViewId()
// Load fragment just once
if (activity.supportFragmentManager.findFragmentById(id) == null) {
activity.supportFragmentManager.beginTransaction()
.replace(id, FeedEmbedFragment.newInstance(embedId = embedId))
.commit()
}
}
},
modifier = modifier
)
}
```
```kotlin Embed With Customization and SSO theme={null}
@Composable
fun StandardWallComposeFragmentWrapper(
modifier: Modifier = Modifier,
embedId: String,
uniqueId: String = "",
ssoToken: String = "",
isDirectDeepLinkEnabled: Boolean = false,
isShowProfileEnabled: Boolean = false,
params: HashMap? = null,
contextualParams: HashMap? = null,
) {
val context = LocalContext.current
val activity = context as? FragmentActivity
?: throw IllegalStateException("Context is not a FragmentActivity")
AndroidView(
factory = { ctx ->
FragmentContainerView(ctx).apply {
id = View.generateViewId()
// Load fragment just once
if (activity.supportFragmentManager.findFragmentById(id) == null) {
val feedEmbedFragment = FeedEmbedFragment.newInstance(
embedId = embedId,
uniqueId = uniqueId,
ssoToken = ssoToken,
isDirectDeepLinkEnabled = isDirectDeepLinkEnabled,
isShowProfileEnabled = isShowProfileEnabled,
params = params,
contextualParams = contextualParams
)
activity.supportFragmentManager.beginTransaction()
.replace(id, feedEmbedFragment)
.commit()
}
}
},
modifier = modifier
)
}
```
Example usage
```kotlin Basic Embed theme={null}
StandardWallComposeFragmentWrapper(
embedId = "YOUR_EMBED_ID",
modifier = Modifier.fillMaxSize()
)
```
```kotlin Embed with Customization and SSO theme={null}
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val contextualParams = HashMap()
contextualParams["page_context"] = "YOUR_CONTEXT_VALUE"
val geoJson = JSONObject()
geoJson.put("lat", XXXX.XXX) // value in double
geoJson.put("long", XXXX.XXX) // value in double
contextualParams["geo"] = geoJson.toString()
StandardWallComposeFragmentWrapper(
embedId = "YOUR_EMBED_ID",
uniqueId = "UNIQUE_ID",
ssoToken = "YOUR_SSO_TOKEN",
isShowProfileEnabled = false,
isDirectDeepLinkEnabled = false,
params = params,
contextualParams = contextualParams,
modifier = Modifier.fillMaxSize()
)
```
We need to pass below arguments in order to cofigure `StandardWallEmbed`.
1. **embedId** = The Embed Id that you want to load.
2. **uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
3. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
4. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
**Note**: For using `isDirectDeepLinkEnabled` parameter, you must have [white labelled your domain](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community) first and also integrated the [Handling deep link](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handling-deep-link) part in your main app in which you want to redirect this video to.
5. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
6. **ssoToken**: This is an optional parameter. To auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN" in order to implement Embed with SSO in your app.
**Add user specific parameters (Optional)**
a. **name** - This is an optional string parameter. Pass this parameter for `signup/login`.
b. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
c. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
d. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
e. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
**Add contextual parameters (Optional)**
a. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
b. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
c. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
## Placement
**1. Load Placement with XML**
```xml activity_placement.xml theme={null}
```
**Note**: Placement Container height must be fixed or match\_parent. It can not be wrap\_content else placement will not appear.
```kotlin PlacementActivity.kt (With SSO) theme={null}
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val geoJson = JSONObject()
geoJson.put("lat", XX.XXX)
geoJson.put("long", XX.XXX)
geoJson.put("radius_limit", )
val placeJson = JSONObject()
placeJson.put("country", "")
placeJson.put("state", "")
placeJson.put("city", "")
placeJson.put("zipcode", )
val userSegmentsJson = JSONObject()
userSegmentsJson.put("age", "")
userSegmentsJson.put("min_age", "")
userSegmentsJson.put("max_age", "")
userSegmentsJson.put("segment", "")
userSegmentsJson.put("gender", "M/F/O")
userSegmentsJson.put("race", "")
val contextualParams = HashMap()
contextualParams["page_context"] = ""
contextualParams["geo"] = geoJson.toString()
contextualParams["place"] = placeJson.toString()
contextualParams["time"] =
contextualParams["user_segments"] = userSegmentsJson.toString()
contextualParams["url"] = "https://url/"
contextualParams["brands_ids"] = JSONArray(arrayListOf(brandId1, brandId2))
contextualParams["community_ids"] = JSONArray(arrayListOf("comm_id1","comm_id2"))
contextualParams["loop_ids"] = JSONArray(arrayListOf("loop_id1", "loop_id2"))
contextualParams["user_interest"] = JSONArray(arrayListOf(""))
contextualParams["posted_by_user_ids"] = JSONArray(arrayListOf("user_id1", "user_id2"))
contextualParams["previous_page_context"] = ""
contextualParams["user_context"] = ""
genuinPlacementView.apply {
setPlacementParams(
placementId = "YOUR_PLACEMENT_ID",
styleId = "YOUR_STYLE_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
)
setActivity(activityContext)
setSSOToken("YOUR_SSO_TOKEN")
setParams(params) // User specific params
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setContextualParams(contextualParams) // Contextual params
load()
}
```
```kotlin PlacementActivity.kt (Without SSO) theme={null}
//This is Optional
val geoJson = JSONObject()
geoJson.put("lat", XX.XXX)
geoJson.put("long", XX.XXX)
geoJson.put("radius_limit", )
val placeJson = JSONObject()
placeJson.put("country", "")
placeJson.put("state", "")
placeJson.put("city", "")
placeJson.put("zipcode", )
val userSegmentsJson = JSONObject()
userSegmentsJson.put("age", "")
userSegmentsJson.put("min_age", "")
userSegmentsJson.put("max_age", "")
userSegmentsJson.put("segment", "")
userSegmentsJson.put("gender", "M/F/O")
userSegmentsJson.put("race", "")
val contextualParams = HashMap()
contextualParams["page_context"] = ""
contextualParams["geo"] = geoJson.toString()
contextualParams["place"] = placeJson.toString()
contextualParams["time"] =
contextualParams["user_segments"] = userSegmentsJson.toString()
contextualParams["url"] = "https://url/"
contextualParams["brands_ids"] = JSONArray(arrayListOf(brandId1, brandId2))
contextualParams["community_ids"] = JSONArray(arrayListOf("comm_id1","comm_id2"))
contextualParams["loop_ids"] = JSONArray(arrayListOf("loop_id1", "loop_id2"))
contextualParams["user_interest"] = JSONArray(arrayListOf(""))
contextualParams["posted_by_user_ids"] = JSONArray(arrayListOf("user_id1", "user_id2"))
contextualParams["previous_page_context"] = ""
contextualParams["user_context"] = ""
genuinPlacementView.apply {
setPlacementParams(
placementId = "YOUR_PLACEMENT_ID",
styleId = "YOUR_STYLE_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
)
setActivity(activityContext)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setContextualParams(contextualParams) // Contextual params
load()
}
```
**2. Load Placement Programmatically**
```xml activity_placement.xml theme={null}
```
**Note**: Placement Container height must be fixed or match\_parent. It can not be wrap\_content else placement will not appear.
```kotlin PlacementActivity.kt (With SSO) theme={null}
val genuinPlacementView = GenuinPlacementView(context)
llPlacementContainer.addView(genuinPlacementView)
//This is Optional
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
//This is Optional
val geoJson = JSONObject()
geoJson.put("lat", XX.XXX)
geoJson.put("long", XX.XXX)
geoJson.put("radius_limit", )
val placeJson = JSONObject()
placeJson.put("country", "")
placeJson.put("state", "")
placeJson.put("city", "")
placeJson.put("zipcode", )
val userSegmentsJson = JSONObject()
userSegmentsJson.put("age", "")
userSegmentsJson.put("min_age", "")
userSegmentsJson.put("max_age", "")
userSegmentsJson.put("segment", "")
userSegmentsJson.put("gender", "M/F/O")
userSegmentsJson.put("race", "")
val contextualParams = HashMap()
contextualParams["page_context"] = ""
contextualParams["geo"] = geoJson.toString()
contextualParams["place"] = placeJson.toString()
contextualParams["time"] =
contextualParams["user_segments"] = userSegmentsJson.toString()
contextualParams["url"] = "https://url/"
contextualParams["brands_ids"] = JSONArray(arrayListOf(brandId1, brandId2))
contextualParams["community_ids"] = JSONArray(arrayListOf("comm_id1","comm_id2"))
contextualParams["loop_ids"] = JSONArray(arrayListOf("loop_id1", "loop_id2"))
contextualParams["user_interest"] = JSONArray(arrayListOf(""))
contextualParams["posted_by_user_ids"] = JSONArray(arrayListOf("user_id1", "user_id2"))
contextualParams["previous_page_context"] = ""
contextualParams["user_context"] = ""
genuinPlacementView.apply {
setPlacementParams(
placementId = "YOUR_PLACEMENT_ID",
styleId = "YOUR_STYLE_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
)
setActivity(activityContext)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setSSOToken("YOUR_SSO_TOKEN")
setParams(params) // User specific params
setContextualParams(contextualParams) // Contextual params
load()
}
```
```kotlin PlacementActivity.kt (Without SSO) theme={null}
//This is Optional
val geoJson = JSONObject()
geoJson.put("lat", XX.XXX)
geoJson.put("long", XX.XXX)
geoJson.put("radius_limit", )
val placeJson = JSONObject()
placeJson.put("country", "")
placeJson.put("state", "")
placeJson.put("city", "")
placeJson.put("zipcode", )
val userSegmentsJson = JSONObject()
userSegmentsJson.put("age", "")
userSegmentsJson.put("min_age", "")
userSegmentsJson.put("max_age", "")
userSegmentsJson.put("segment", "")
userSegmentsJson.put("gender", "M/F/O")
userSegmentsJson.put("race", "")
val contextualParams = HashMap()
contextualParams["page_context"] = ""
contextualParams["geo"] = geoJson.toString()
contextualParams["place"] = placeJson.toString()
contextualParams["time"] =
contextualParams["user_segments"] = userSegmentsJson.toString()
contextualParams["url"] = "https://url/"
contextualParams["brands_ids"] = JSONArray(arrayListOf(brandId1, brandId2))
contextualParams["community_ids"] = JSONArray(arrayListOf("comm_id1","comm_id2"))
contextualParams["loop_ids"] = JSONArray(arrayListOf("loop_id1", "loop_id2"))
contextualParams["user_interest"] = JSONArray(arrayListOf(""))
contextualParams["posted_by_user_ids"] = JSONArray(arrayListOf("user_id1", "user_id2"))
contextualParams["previous_page_context"] = ""
contextualParams["user_context"] = ""
val genuinPlacementView = GenuinPlacementView(context)
llPlacementContainer.addView(genuinPlacementView)
genuinPlacementView.apply {
setPlacementParams(
placementId = "YOUR_PLACEMENT_ID",
styleId = "YOUR_STYLE_ID",
uniqueId="UNIQUE_ID",
interactionDeepLink = "YOUR_DEEPLINK",
isDirectDeepLinkEnabled = false,
)
setActivity(activityContext)
setInterTileSpacing(24) // values should be in pixels
setInsets(
left = 24, // values should be in pixels
top = 24, // values should be in pixels
right = 24, // values should be in pixels
bottom = 24, // values should be in pixels
)
setTileCornerRadius(24) // values should be in pixels
setContextualParams(contextualParams) // Contextual params
load()
}
```
**Note**: To initialise the Placement you need to add your activity context `(setActivity(activityContext))` in which you want the placement. To auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN"`(setSSOToken("YOUR_SSO_TOKEN"))` in order to implement Placement with SSO in your app.
To configure the `PlacementParams` based on your need you can pass the below values.
1. **placementId** = The Placement Id that you want to load.
2. **styleId** = The Style Id that you want to load.
3. **uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same placement in multiple/same screen. We need to provide uniqueId for the same placementId in multiple/same screen.
4. **interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
5. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
**Note**: For using `isDirectDeepLinkEnabled` parameter, you must have [white labelled your domain](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community) first and also integrated the [Handling deep link](https://resources.begenuin.com/developers/sdk-docs/android_sdk#handling-deep-link) part in your main app in which you want to redirect this video to.
**Add user specific parameters (Optional)**
a. **name** - This is an optional string parameter. Pass this parameter for `signup/login`.
b. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
c. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
d. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
e. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
**Add contextual parameters (Optional)**
a. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
b. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
c. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
**Add design configurations (Optional)**
a. **interTileSpacing** - spacing between the carousel's view items. It's default value is `8dp`
b. **Inset** - edge insets for placement's view. It's default value is `top: 8dp, left: 16dp, bottom: 0dp, right: 16dp`
c. **tileCornerRadius** - cornerRadius for the carousel's view items. It's default value is `8dp`
**3. Manage carousel videos auto-play**
```kotlin PlacementActivity.kt theme={null}
override fun onResume() {
super.onResume()
genuinPlacementView.play()
}
override fun onPause() {
genuinPlacementView.pause()
super.onPause()
}
override fun onDestroy() {
genuinPlacementView.release()
super.onDestroy()
}
```
**4. Load placement feed asynchronously:**
In order to load placement feeds asynchronously, instead of calling load(), use loadAsync with a callback (as shown). This callback will be triggered once the process of fetching data is complete, along with a boolean flag indicating whether the operation was successful and non-empty feed was retrieved.
```Kotlin activity_full_placement.xml theme={null}
genuinPlacementView.loadAsync {
success ->
if (success) {
binding.genuinPlacementView.visibility = View.VISIBLE
}
}
```
## Handle Login : via AutoLogin Approach
To Auto Login in the SDK, You need to call below method, whenever user is log in to your application.
**Note**: You don't need to call the below method if you have implemented the Embed/Placement With SSO already.
```kotlin YourClass.kt theme={null}
GenuinSDK.ssoLogin(context = "YOUR_CONTEXT", ssoToken = "YOUR_SSO_TOKEN")
```
### Optional Parameters
Below are the optional parameters you can add with the function:
```kotlin YourActivity.kt theme={null}
val params = HashMap()
params["name"] = "John Doe"
params["email"] = "john.doe@begenuin.com"
params["nickname"] = "john"
params["mobile"] = "1XXXXXXXXXX"
GenuinSDK.ssoLogin(
context = "YOUR_CONTEXT",
ssoToken = "YOUR_SSO_TOKEN",
params = params //This is optional
)
```
**Add user specific parameters (Optional)**
1. **name** - This is an optional string parameter. Pass this parameter for '`signup/login`'.
2. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
3. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
4. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
5. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
### Optional Callback
```kotlin YourClass.kt theme={null}
GenuinSDK.ssoLogin(
context = "YOUR_CONTEXT",
ssoToken = "YOUR_SSO_TOKEN",
params = "YOUR_OPTIONAL_PARAMS",
onComplete = {
isSuccess: Boolean ->
//Manage callback for Login Completion
}
)
```
```kotlin YourClass.java theme={null}
GenuinSDK.INSTANCE.ssoLogin(
"CONTEXT",
"SSO-TOKEN",
"OPTIONAL-PARAMETERS",
(isSuccess) -> {
//Manage callback for Login Completion
return Unit.INSTANCE;
}
);
```
## Custom Login
If you want to handle login process as per your requirement then follow the below steps:
```kotlin YourActivity.kt theme={null}
GenuinSDK.registerInterface(object : GenuinInterface {
override fun onLogin(context: Activity) {
/*
This callback will be triggered when user attempts to login
within one of the Genuin embeds. Application login process
should be initiated here.
When your application's auth process is successfully completed,
call GenuinSDK.ssoLogin(context, "ssoToken") to automatically
manage SDK login.
*/
}
})
```
## Handle Logout : via AutoLogin Approach
Whenever user logs out from your application call the below method.
GenuinSDK.ssoLogout(context = "YOUR\_CONTEXT")
### Optional Callback
```kotlin YourClass.kt theme={null}
GenuinSDK.ssoLogout(
context = "YOUR_CONTEXT",
onComplete = {
isSuccess: Boolean ->
//Manage callback for Logout Completion
}
)
```
```kotlin YourClass.java theme={null}
GenuinSDK.INSTANCE.ssoLogout(
"CONTEXT",
(isSuccess) -> {
//Manage callback for Logout Completion
return Unit.INSTANCE;
}
);
```
## Handling Deep Link
**Note**: Make sure you have followed the [First 3 installation steps](https://resources.begenuin.com/developers/sdk-docs/android_sdk#installation) in order to handle the deep link.
**Prerequisite**:
1. Make sure you have white labelled your community by following these [steps](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community).
2. Follow the steps given in the below URL to integrate deeplink in your app
[https://developer.android.com/studio/write/app-link-indexing](https://developer.android.com/studio/write/app-link-indexing)
**Note** : Here host will be your "YOUR\_WHITE-LABELLED\_DOMAIN"
3. After completing deeplink setup, your `assetlinks.json` file should look like below
```kotlin assetlinks.json theme={null}
[{"target":{"package_name":"YOUR_PACKAGE_NAME","sha256_cert_fingerprints":["YOUR_KEYSTORE'S_SHA256_FINGERPRINTS"],"namespace":"android_app"},"relation":["delegate_permission/common.handle_all_urls"]}]
```
4. Host `assetlinks.json` file on the white labeled domain at `https://YOUR_WHITE-LABELLED_DOMAIN/.well-known/assetlinks.json`
**To Handle Our Deep Link In Your App**
You can call the below method immediately after receiving deeplink or you can wait until your app's home screen is loaded.
```kotlin YourCustomActivity.kt theme={null}
GenuinSDK.handleDeepLink(context = "YOUR_CONTEXT", intent = "YOUR_DEEPLINK_ACTIVITY_INTNET")
```
**Note**: Need to call this function everytime your app receives any deeplink. This method will handle deeplink if it is our's otherwise it will ignore that.
### Optional LinkOutInterceptor
If you want to intercept Linkout clicks, you can implement `LinkOutInterceptor` as below:
```kotlin YourActivity.kt theme={null}
GenuinSDK.registerLinkOutInterceptor(object : GenuinLinkOutInterceptor {
override fun onLinkOutIntercept(intent: Intent, context: Activity) {
/*
This callback will be triggered when user clicks on linkouts
from any video and if it is found that link is handled by your app.
You will receive whole intent data same as we will be receiving while
deeplink is clicked so you can handle the deeplink redirection from here
in your app
*/
}
})
```
## Handling Push Notifications
**Note**: Make sure you have followed the [First 3 installation steps](https://resources.begenuin.com/developers/sdk-docs/android_sdk#installation) in order to handle the push notifications.
**Prerequisite:**
1. Create an app in your firebase using [these steps](https://firebase.google.com/docs/android/setup)
2. Download the `google-services.json` file and add it into your app.
3. Integrate firebase into your app by following [these steps](https://firebase.google.com/docs/cloud-messaging/android/client)
**Get firebase token and register it with Genuin SDK**
```kotlin theme={null}
private fun getFirebaseToken(){
FirebaseMessaging.getInstance().token
.addOnCompleteListener { task: Task ->
if (!task.isSuccessful) {
return@addOnCompleteListener
}
// Get new FCM registration token
val token = task.result
// Register token with Genuin SDK
GenuinSDK.registerFCMToken("YOUR_CONTEXT", token)
}
}
```
**Handle foreground notifications (When your app is in foreground)**
```kotlin MyFirebaseMessagingService.kt theme={null}
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
val data: Map = remoteMessage.getData()
if (GenuinSDK.willHandleForegroundNotification(data)) {
val message = remoteMessage.notification?.body ?: ""
GenuinSDK.handleForegroundNotifications(
context = this,
data = data,
message = message,
smallNotificationIcon = R.drawable.ic_small_notifications // Your app's notification small icon
)
} else {
// Handle other push notifications for your app
}
}
/**
* There are two scenarios when onNewToken is called:
* 1) When a new token is generated on initial app startup
* 2) Whenever an existing token is changed
* Under #2, there are three scenarios when the existing token is changed:
* A) App is restored to a new device
* B) User uninstalls/reinstall the app
* C) User clears app data
*/
override fun onNewToken(s: String) {
super.onNewToken(s)
GenuinSDK.registerFCMToken(this, s)
}
}
```
**Note**: `GenuinSDK.willHandleForegroundNotification(data: Map)` function will check whether GenuinSDK will handle the given notification or not when app is in foreground.
**Handle notifications while app is running in background or closed**
* Whenever user clicks on notifications, you will get the notification payload in your launcher activity.
```kotlin YourLauncherActivity.kt theme={null}
if (GenuinSDK.willHandleNotification(intent)) {
GenuinSDK.handleBackgroundNotifications(context = "YOUR_CONTEXT", intent)
}
```
**Note**: `GenuinSDK.willHandleNotification(intent: Intent)` function will check whether GenuinSDK will handle the given notification or not.
## What’s next?
Integrate iOS SDK in Your ecosystem.
Integrate Web SDK in your ecosystem.
Integrate React Native SDK in your ecosystem.
## Support
If you need any assistance or have any questions, feel free to email us at [support@begenuin.com](mailto:support@begenuin.com).
# Flutter SDK
Source: https://resources.begenuin.com/developers/sdk-docs/flutter_sdk
Flutter SDK comprises features such as brand feed, communities, and groups.
## Requirements
| Platform | Minimum SDK Version | Language | Supported Orientations | Supported Destinations |
| -------- | ------------------- | ----------- | ---------------------- | ---------------------- |
| Android | 24 | Java/Kotlin | Portrait | Mobile |
| iOS | 13.0 | Swift | Portrait | iPhone |
## Android
### Installation
Follow the below steps and place the codes in mentioned files to install the Flutter SDK in Android.
**Step 1**: In `android/build.gradle`:
```swift android/build.gradle theme={null}
allprojects {
repositories {
google()
mavenCentral()
// Add jitpack
maven {
setUrl("https://jitpack.io")
}
}
}
```
**Step 2**: In `android/app/build.gradle`:
```swift android/app/build.gradle theme={null}
android {
defaultConfig {
minSdk = 24
}
}
```
**Step 3**: In `android/app/src/main/AndroidManifest.xml:`:
```swift android/app/src/main/AndroidManifest.xml theme={null}
```
**Step 4**: Change Theme in `android/app/src/main/res/values/styles.xml`:
Our SDK is using `Material` components so in order to use our sdk you need to use material theme as shown in below example
```swift android/app/src/main/res/values/styles.xml theme={null}
```
**Step 5**: Create `android/app/proguard-rules.pro`, add the following lines:
```swift android/app/build.gradle theme={null}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
-keep class com.bumptech.glide.**{*;}
-keep public class * {
public *;
protected *;
}
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@retrofit2.http.* ;
}
# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit
# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn java.lang.reflect.AnnotatedType
-dontwarn com.google.api.client.http.GenericUrl
-dontwarn com.google.api.client.http.HttpHeaders
-dontwarn com.google.api.client.http.HttpRequest
-dontwarn com.google.api.client.http.HttpRequestFactory
-dontwarn com.google.api.client.http.HttpResponse
-dontwarn com.google.api.client.http.HttpTransport
-dontwarn com.google.api.client.http.javanet.NetHttpTransport$Builder
-dontwarn com.google.api.client.http.javanet.NetHttpTransport
-dontwarn com.squareup.picasso.Picasso
-dontwarn com.squareup.picasso.RequestCreator
-dontwarn java.awt.image.BufferedImage
-dontwarn javax.imageio.ImageIO
-dontwarn org.joda.time.Instant
-dontwarn org.junit.Assert
-dontwarn org.slf4j.impl.StaticLoggerBinder
-dontwarn org.slf4j.impl.StaticMDCBinder
-dontwarn org.slf4j.impl.StaticMarkerBinder
# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* ; }
-keep,allowobfuscation interface <1>
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.begenuin.begenuin.data.model.** { ; }
-keep class com.begenuin.begenuin.vo.** { ; }
# RenderScript
-keepclasseswithmembernames class * {
native ;
}
-keep class androidx.renderscript.** { *; }
-keepattributes *Annotation*
-keep class com.giphy.sdk.core.models.** { *; }
-keep class com.giphy.sdk.ui.views.** { *; }
-keep public class * implements java.lang.reflect.Type
-keep class com.google.mediapipe.solutioncore.** {*;}
-keep class com.google.protobuf.** {*;}
-dontwarn com.begenuin.sdk.BR
-dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManager
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManagerFactory
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest$Builder
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest
-dontwarn com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
-dontwarn com.google.android.play.core.tasks.OnFailureListener
-dontwarn com.google.android.play.core.tasks.OnSuccessListener
-dontwarn com.google.android.play.core.tasks.Task
-dontwarn com.google.mediapipe.proto.CalculatorProfileProto$CalculatorProfile
-dontwarn com.google.mediapipe.proto.GraphTemplateProto$CalculatorGraphTemplate
-dontwarn javax.lang.model.AnnotatedConstruct
-dontwarn javax.lang.model.SourceVersion
-dontwarn javax.lang.model.element.AnnotationMirror
-dontwarn javax.lang.model.element.AnnotationValue
-dontwarn javax.lang.model.element.AnnotationValueVisitor
-dontwarn javax.lang.model.element.Element
-dontwarn javax.lang.model.element.ElementKind
-dontwarn javax.lang.model.element.ElementVisitor
-dontwarn javax.lang.model.element.ExecutableElement
-dontwarn javax.lang.model.element.Name
-dontwarn javax.lang.model.element.NestingKind
-dontwarn javax.lang.model.element.PackageElement
-dontwarn javax.lang.model.element.QualifiedNameable
-dontwarn javax.lang.model.element.TypeElement
-dontwarn javax.lang.model.element.TypeParameterElement
-dontwarn javax.lang.model.element.VariableElement
-dontwarn javax.lang.model.type.ArrayType
-dontwarn javax.lang.model.type.DeclaredType
-dontwarn javax.lang.model.type.ErrorType
-dontwarn javax.lang.model.type.ExecutableType
-dontwarn javax.lang.model.type.IntersectionType
-dontwarn javax.lang.model.type.NoType
-dontwarn javax.lang.model.type.NullType
-dontwarn javax.lang.model.type.PrimitiveType
-dontwarn javax.lang.model.type.TypeKind
-dontwarn javax.lang.model.type.TypeMirror
-dontwarn javax.lang.model.type.TypeVariable
-dontwarn javax.lang.model.type.TypeVisitor
-dontwarn javax.lang.model.type.WildcardType
-dontwarn javax.lang.model.util.AbstractElementVisitor8
-dontwarn javax.lang.model.util.ElementFilter
-dontwarn javax.lang.model.util.Elements
-dontwarn javax.lang.model.util.SimpleAnnotationValueVisitor8
-dontwarn javax.lang.model.util.SimpleElementVisitor8
-dontwarn javax.lang.model.util.SimpleTypeVisitor8
-dontwarn javax.lang.model.util.Types
-dontwarn javax.tools.Diagnostic$Kind
-dontwarn javax.tools.JavaFileObject$Kind
-dontwarn javax.tools.JavaFileObject
-dontwarn javax.tools.SimpleJavaFileObject
```
Want to override our default loader?
* We are using `lottie` animation for our loader. You can put your custom `lottie animation` loader with the name `loader_mix.json` in the `android/app/src/main/res/raw` folder. Make sure you use the same name as provided.
### Quick Start
**1. Initialize SDK**
Place the below code in `android/app/src/main/yourpackage/MainActivity.kt` file to initialize the SDK.
```swift theme={null}
import android.content.Intent
import android.os.Bundle
import com.begenuin.genuin_sdk.GenuinSdkPlugin
import io.flutter.embedding.android.FlutterFragmentActivity
// Here we need to use FlutterFragmentActivity instead of FlutterActivity
class MainActivity : FlutterFragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GenuinSdkPlugin.initSDK(this@MainActivity, "YOUR_API_KEY")
}
}
```
**2. Handling Deep Link**
To handle deep link place the below code in `android/app/src/main/AndroidManifest.xml` file:
```swift theme={null}
```
Place the below code in `android/app/src/main/yourpackage/MainActivity.kt` file:
```swift theme={null}
import android.content.Intent
import android.os.Bundle
import com.begenuin.genuin_sdk.GenuinSdkPlugin
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity : FlutterFragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GenuinSdkPlugin.initSDK(this@MainActivity, "YOUR_API_KEY")
handleDeepLink(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleDeepLink(intent)
}
private fun handleDeepLink(intent: Intent?) {
intent?.data?.let {
GenuinSdkPlugin.handleDeepLink(this@MainActivity, intent)
}
}
}
```
## iOS
### iOS Configuration
Follow the below steps and place the codes in mentioned files to install the Flutter SDK in iOS.
**1. In ios/Podfile:**
```kotlin ios/Podfile theme={null}
# Uncomment this line to define a global platform for your project
platform :ios, '13.0'
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
if target.name == 'Giphy'
`xcrun -sdk iphoneos bitcode_strip -r Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK -o Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK`
end
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
```
### Quick Start
**1. Initialize SDK**
```kotlin theme={null}
import Flutter
import UIKit
import genuin_sdk
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GenuinSdkPlugin.initialize(apiKey: "YOUR_API_KEY", loaderName: "YOUR_LOTTIE_LOADER_NAME")
//We are using lottie animation for our loader. You can put your custom lottie animation loader in your app's resources. update the "YOUR_LOTTIE_LOADER_NAME" with your loader name while initialize sdk.
GeneratedPluginRegistrant.register(with: self)
//UINavigationController is required for the redirection purpose in native component
if let flutterViewController: FlutterViewController = window?.rootViewController as? FlutterViewController {
let navigationController = UINavigationController(rootViewController: flutterViewController)
navigationController.setNavigationBarHidden(true, animated: false)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
```
**2. Handling Deep Link**
To handle deeplink place the below in `AppDelegate.swift` file:
```swift AppDelegate.swift theme={null}
import Flutter
import UIKit
import genuin_sdk
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GenuinSdkPlugin.initialize(apiKey: "YOUR_API_KEY", loaderName: "YOUR_LOTTIE_LOADER_NAME")
GeneratedPluginRegistrant.register(with: self)
if let flutterViewController: FlutterViewController = window?.rootViewController as? FlutterViewController {
let navigationController = UINavigationController(rootViewController: flutterViewController)
navigationController.setNavigationBarHidden(true, animated: false)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
let result = GenuinSdkPlugin.flutterapplication(application, continue: userActivity, restorationHandler: restorationHandler)
if GenuinSdkPlugin.handleDeepLink(dlURL: userActivity.webpageURL, controller: window?.rootViewController) {
return true
}
return result
}
}
```
**3. Handling Push Notification**
To handle the push notification place the below code In `AppDelegate.swift` file:
```kotlin theme={null}
import Flutter
import UIKit
import genuin_sdk
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GenuinSdkPlugin.initialize(apiKey: "YOUR_API_KEY", loaderName: "YOUR_LOTTIE_LOADER_NAME")
UNUserNotificationCenter.current().delegate = self
GeneratedPluginRegistrant.register(with: self)
if let flutterViewController: FlutterViewController = window?.rootViewController as? FlutterViewController {
let navigationController = UINavigationController(rootViewController: flutterViewController)
navigationController.setNavigationBarHidden(true, animated: false)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print("\(userInfo )")
completionHandler(.newData)
}
override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
print("\(userInfo)")
//removed banner to show in app notification
if #available(iOS 14.0, *) {
completionHandler([.banner, .list, .badge, .sound])
} else {
// Fallback on earlier versions
completionHandler([])
}
}
}
```
## Flutter
**1. Load Feed View**
```dart theme={null}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Genuin SDK Example'),
),
body: GenuinFeedView(),
),
);
}
```
**2. Load Carousel Embed View**
```dart theme={null}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Genuin SDK Example'),
),
body: SizedBox(
height: 400, // here you can give height as per your need.
width: MediaQuery
.of(context)
.size
.width, // here you can give width as per your need.
child: const GenuinCarouselEmbedView(
embedId: "YOUR_EMBED_ID",
uniqueId: "UNIQUE_ID",
ssoToken: "YOUR_SSO_TOKEN",
isShowProfileEnabled: false,
isDirectDeepLinkEnabled: false,
),
),
),
);
}
```
To configure the EmbedParams based on your need you can pass the below values.
**embedId** = The Embed Id that you want to load.
**uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
**ssoToken** = This is an optional parameter. To auto login in the SDK, you shall pass “YOUR\_SSO\_TOKEN” in order to implement Embed with SSO in your app.
**interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
**isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter “interactionDeepLink” will be ignored. If not passed then the regular flow will work.
**Note**: For using isDirectDeepLinkEnabled parameter, you must have white labelled your domain first and also integrated the Handling deep link part in your main app in which you want to redirect this video to.
**isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
**3. Load Full Screen/Standard Wall Embed View**
```dart theme={null}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Genuin SDK Example'),
),
body: SizedBox(
height: MediaQuery
.of(context)
.size
.height, // here you can give height as per your need.
width: MediaQuery
.of(context)
.size
.width, // here you can give width as per your need.
child: const GenuinFeedEmbedView(
embedId: "YOUR_EMBED_ID",
uniqueId: "UNIQUE_ID",
ssoToken: "YOUR_SSO_TOKEN",
isShowProfileEnabled: false,
isDirectDeepLinkEnabled: false,
),
),
),
);
}
```
To configure the EmbedParams based on your need you can pass the below values.
**embedId** = The Embed Id that you want to load.
**uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
**ssoToken** = This is an optional parameter. To auto login in the SDK, you shall pass “YOUR\_SSO\_TOKEN” in order to implement Embed with SSO in your app.
**interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
**isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter “interactionDeepLink” will be ignored. If not passed then the regular flow will work.
**Note**: For using isDirectDeepLinkEnabled parameter, you must have white labelled your domain first and also integrated the Handling deep link part in your main app in which you want to redirect this video to.
**isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
**4. Handling Push Notifications**
**Prerequisite**:
Create firebase project and integrate into your app by following [https://firebase.google.com/docs/flutter/setup](https://firebase.google.com/docs/flutter/setup)
Step 1: Create `firebase_options.dart` in lib folder and add below details in that file.
```dart theme={null}
import 'package:firebase_core/firebase_core.dart';
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (Platform.isAndroid) {
return const FirebaseOptions(
apiKey: 'YOUR-ANDROID-API-KEY',
appId: 'YOUR-ANDROID-APP-ID',
messagingSenderId: 'YOUR-SENDER-ID',
projectId: 'YOUR-PROJECT-ID',
storageBucket: 'YOUR-STORAGE-BUCKET',
);
}else{
return const FirebaseOptions(
apiKey: 'YOUR-IOS-API-KEY',
appId: 'YOUR-IOS-APP-ID',
messagingSenderId: 'YOUR-SENDER-ID',
projectId: 'YOUR-PROJECT-ID',
storageBucket: 'YOUR-STORAGE-BUCKET',
);
}
}
}
```
**2. Handling background/foreground notifications**
**Note**: Here for Android you need to provide small notification icon as "icon" key for foreground notifications. This icon needs to be in your flutter as well as android folder.
```dart theme={null}
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:genuin_sdk/genuin_sdk.dart';
import 'firebase_options.dart';
// This method will be called when app is in background and push received
Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
}
final _genuinSdkPlugin = GenuinSdk();
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
name: 'YOUR_FIREBASE_PROJECT_NAME',
options: DefaultFirebaseOptions.currentPlatform,
);
final messaging = FirebaseMessaging.instance;
// Asking push notification permission
final settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
// If permission is granted than get firebase token and register it with Genuin SDK
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
String? token = await messaging.getToken();
if (token != null) {
await _genuinSdkPlugin.registerFCMToken(token);
}
}
// Check for initial notification that opened the app
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) {
// Handle navigation or actions
final notificationData = {
'title': initialMessage.notification?.title,
'body': initialMessage.notification?.body,
'data': initialMessage.data,
};
var willHandleNotification = await _genuinSdkPlugin
.willHandleBackgroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleBackgroundNotifications(notificationData);
} else {
// Your notification handling
}
}
// This method will be called when app is in foreground and push received
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
if (kDebugMode) {
print('Handling a foreground message: ${message.messageId}');
print('Message data: ${message.data}');
print('Message notification: ${message.notification?.title}');
print('Message notification: ${message.notification?.body}');
}
final notificationData = {
'title': message.notification?.title,
'body': message.notification?.body,
'data': message.data,
'icon': 'mipmap/ic_notification'
// OR 'icon':'drawable/ic_notification'[if image put under drawable folder]
};
var willHandleNotification = await _genuinSdkPlugin
.willHandleForegroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleForegroundNotifications(notificationData);
} else {
// Your notification handling
}
});
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
//This method will be called when user clicked on notification[Push notification is received when app is in background/killed]
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
final notificationData = {
'title': message.notification?.title,
'body': message.notification?.body,
'data': message.data,
};
var willHandleNotification = await _genuinSdkPlugin
.willHandleBackgroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleBackgroundNotifications(notificationData);
} else {
// Your notification handling
}
});
runApp(const MyApp());
}
```
**Step 5**. Handle SSO Login Explicitly in SDK
To Auto Login in the SDK, You need to call below method, whenever user is log in to your application.
**Note**: You don’t need to call the below method if you have implemented the Embed With SSO already.
```dart theme={null}
import 'package:genuin_sdk/genuin_sdk.dart';
final _genuinSdkPlugin = GenuinSdk();
await _genuinSdkPlugin.ssoLogin("YOUR_SSO_TOKEN");
```
**Step 6. Handle SSO Logout in SDK**
Whenever user logs out from your application call the below method.
```dart theme={null}
import 'package:genuin_sdk/genuin_sdk.dart';
final _genuinSdkPlugin = GenuinSdk();
await _genuinSdkPlugin.ssoLogout();
```
# Integration Methods
Source: https://resources.begenuin.com/developers/sdk-docs/integration_methods
Genuin offers two primary integration methods for brands to integrate:
1. **Provide Repository Access:** Grant access to your existing mobile project repository to the Genuin team.
2. **Fork Repository:** Genuin will fork the repository and integrate the SDK code into it.
3. **QA Check:** Genuin will perform a comprehensive QA check across the app to ensure seamless integration of the SDK.
4. **Merge Changes:** Once QA is completed, Genuin will provide the changes back to your repository.
*Currently we do not charge for managed service for enterprise customers. Requests are prioritized based on the priority of the customer integration and developer’s availability. We will try to speed up every integration that comes our way.*
**Integrate SDK into Your Project::**
1. Follow the step-by-step instructions provided in the documentation for your respective platform (Android or iOS).
2. Make sure to import and configure any required SDK settings.
# iOS SDK
Source: https://resources.begenuin.com/developers/sdk-docs/ios_sdk
Genuin iOS SDK comprises features such as brand feed, communities, and groups.
## Requirements
| Platform | Minimum Deployment Target | Language | Supported Orientations | Supported Destinations |
| -------- | ------------------------- | -------- | ---------------------- | ---------------------- |
| iOS | 13.0 | Swift | Portrait | iPhone |
## Permissions (Optional)
Permissions to be added in `info.plist` file of your application
| Permission | Usage | Used Where |
| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| Camera (NSCameraUsageDescription) | Genuin needs permissions to open your camera and microphone. This allows Genuin to record videos that can be shared with other people. | Post, Video Comment |
| Microphone (NSMicrophoneUsageDescription) | Genuin needs permissions to open your camera and microphone. This allows Genuin to record videos that can be shared with other people. | Post, Voice Comment |
| Photos (NSPhotoLibraryUsageDescription) | Genuin needs permissions to access your photo library. This allows Genuin to download videos to your phone and save it to your library. | Post, Profile, Banner |
| Speech Recognition (NSSpeechRecognitionUsageDescription) | The transcript of your recording will be displayed to you in the end for you to overlay it on the audio message. | To generate transcript from recorded audio |
| Contacts (NSContactsUsageDescription) | Genuin requires to sync with your contacts and provide a better experience when you wish to share your posts with them. | Add Members in Communities and Groups |
| Location (NSLocationWhenInUseUsageDescription) | Your precise location will help us suggest your community details more accurately. | AI Powered Communities based on the User Location |
| Tracking (NSUserTrackingUsageDescription) | Your data will be used to analyse ads we run! | Monetization |
If any permission is not given then that particular feature will not be accessible in your app.
## Installation
### Standard CocoaPods Install
If your project doesn't have the CocoaPods setup then start with `pod init` which will create the Podfile, else do following changes in the pod file to install GenuinSDK.
```swift Podfile.swift theme={null}
platform :ios, '13.0'
target 'YourProject' do
use_frameworks!
# Pods for YourProject
pod "GenuinSDK", :git => "https://bitbucket.org/genuindev/genuin_sdk_ios.git", :tag => "1.1.17.1"
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
```
If you are using Xcode 16 then kindly refer the below podfile :
```swift Podfile.swift theme={null}
platform :ios, '13.0'
target 'YourProject' do
use_frameworks!
pod "GenuinSDK", :git => "https://bitbucket.org/genuindev/genuin_sdk_ios.git", :tag => "1.1.17.1"
end
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'Giphy'
`xcrun -sdk iphoneos bitcode_strip -r Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK -o Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK`
end
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
```
**Example**
Import the GenuinSDK module in your `SceneDelegate/AppDelegate`.
```swift SceneDelegate.swift theme={null}
import GenuinSDK
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Optional configuration and attaching the UIWindow to UIWindowScene
guard let _ = (scene as? UIWindowScene) else { return }
// Initialize the SDK configuration
let configuration = GenuinConfiguration.shared
// For Production environment (Default)
configuration.setCustomLoader("YOUR_LOADER", bundle: .main)
// For QA Environment
configuration.environment = .qa
// Initialize the SDK with your API key and configuration
GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)
// Notify the SDK that the scene will connect
GenuinSDK.shared.scene(scene, willConnectTo: session, options: connectionOptions)
}
```
```swift AppDelegate.swift theme={null}
import GenuinSDK
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize the SDK configuration
let configuration = GenuinConfiguration.shared
// For Production Environment (Default)
configuration.setCustomLoader("YOUR_LOADER", bundle: .main)
// For QA Environment
configuration.environment = .qa
// Initialize the SDK with your API key and configuration
GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)
return true
}
```
To load your lottie animation accross the Genuin SDK, you can add it here `configuration.setCustomLoader("YOUR_LOADER", bundle: .main)`
### Instructions for `SceneDelegate`:
1. Ensure you are using the `UISceneDelegate` in your app.
2. In your `SceneDelegate.swift` file, implement the `scene(_:willConnectTo:options:)` method.
3. Use the shared configuration and set up any custom loaders or additional parameters.
4. Call `GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)` with your API key and the configured options.
5. Ensure that `GenuinSDK.shared.scene(scene, willConnectTo: session, options: connectionOptions)` is called to notify the SDK of the scene connection.
### Instructions for `AppDelegate`:
1. In your `AppDelegate.swift`, implement the `application(_:didFinishLaunchingWithOptions:)` method.
2. Set up the shared configuration and initialize the SDK with your API key.
3. Call `GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)` with your API key and the configured options.
4. Return `true` to indicate successful launch configuration.
Then you can display the home feed view controller. For example, to use it in your `UITabBarController`:
```swift ViewController.swift theme={null}
import UIKit
import GenuinSDK
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
if let homeFeedController = GenuinSDK.shared.getHomeScreen() {
homeFeedController.tabBarItem = UITabBarItem(title: "Community", image: UIImage(systemName: "person.3"), tag: 0)
self.viewControllers = [homeFeedController]
}
}
}
```
To present feed from your UIViewController by clicking on UIButton:
```swift ViewController.swift theme={null}
import UIKit
import GenuinSDK
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func openFeed() {
if let vc = GenuinSDK.shared.getHomeScreen() {
vc.navigationBar.isTranslucent = false
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true)
}
}
}
```
**Note**: Our SDK is well optimized for `iOS version 15.0` and above, but if you are using `iOS version 13` or `14` then put this `if #available(iOS 15.0, *)` condition while importing the GenuinSDK. Refer to the below code block
```swift ViewController.swift theme={null}
// Below is an Example Code
if #available(iOS 15.0, *) {
// Initialize the SDK with your API key and configuration
GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)
if let vc = GenuinSDK.shared.getHomeScreen() {
vc.tabBarItem = UITabBarItem(title: "Community", image: UIImage(systemName: "person.3"), tag: 3)
self.viewControllers = [vc]
self.selectedIndex = 0
}
}
```
## Monetization
To enable Monetization use following code snippet to get **advertisingIdentifier** by **AppTrackingTranspancy**. You need to add `NSUserTrackingUsageDescription` in `Info.plist` as described [here](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#permissions-optional).
```swift For SceneDelegate theme={null}
import AppTrackingTransparency
import AdSupport //Import only if you want to use advertisingIdentifier
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
DispatchQueue.main.async {
ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .notDetermined:
break
case .restricted:
break
case .denied:
break
case .authorized:
// If you want to check the current advertisingIdentifier
print("advertisingIdentifier: ", ASIdentifierManager.shared().advertisingIdentifier.uuidString)
break
@unknown default:
break
}
}
}
}
}
```
```swift For AppDelegate theme={null}
import AppTrackingTransparency
import AdSupport //Import only if you want to use advertisingIdentifier
class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationDidBecomeActive(_ application: UIApplication) {
DispatchQueue.main.async {
ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .notDetermined:
break
case .restricted:
break
case .denied:
break
case .authorized:
// If you want to check the current advertisingIdentifier
print("advertisingIdentifier: ", ASIdentifierManager.shared().advertisingIdentifier.uuidString)
break
@unknown default:
break
}
}
}
}
}
```
Also if you enable monetization then you need to update App Privacy in AppStoreConnect
**Need to declare in App Store Connect that your app is using Advertising Data**
Steps:
* **Log in** to your App Store Connect.
* **Select the app** you are working on.
* Go to App **Privacy > Data Collection**.
* Find the Usage Data section and select the **Advertising Data**.
* Click on **Save/Publish**.
* Now Setup Advertising Data by selecting (Third-Party Advertising, Analytics, Product Personalization, App Functionality, Other Purposes)
* Click on **Next** and give the answers as asked.
* Click on **save**.
## Embed
**Note**: Make sure you have followed the [installation steps](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#installation) in order to implement the Carousel Embed.
### Carousel Embed
Refer to [Carousel View](https://resources.begenuin.com/developers/guides/embed#mobile-view) in Mobile
```swift ViewController.swift (With SSO) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbed(embedId: "YOUR_EMBED_ID", containerView: , viewConroller: , ssoToken: , embedConfiguration: embedConfiguration)
```
```swift ViewController.swift (Without SSO) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbed(embedId: "YOUR_EMBED_ID", containerView: , viewConroller: , embedConfiguration: embedConfiguration)
```
```swift ViewController.swift (With Contextual Parameters) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NO"], contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
**Note**: To fetch the Embed you need to add `YOUR_EMBED_ID`, `YOUR_CONTAINER_VIEW` in which you want the embed, and `YOUR_VIEW_CONTROLLER` containing your container view, while calling the below function. For auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN" in order to implement Embed with SSO in your app.
#### Vertical Carousel Embed
In `EmbedConfiguration` there is new option called `genuinCarouselConfiguration` by using it we can change the configs of carousel design.
```swift ViewController.swift theme={null}
// Below is an Example Code
let genuinCarouselConfiguration = GenuinCarouselConfiguration()
genuinCarouselConfiguration.interTileSpacing = 16.0
genuinCarouselConfiguration.scrollDirection = .vertical //default value is .horizontal as described above.
genuinCarouselConfiguration.tileCornerRadius = 16.0
genuinCarouselConfiguration.aspectRatio = .ratio4x5
let embedConfiguration = EmbedConfiguration()
embedConfiguration.genuinCarouselConfiguration = genuinCarouselConfiguration //here you can pass the GenuinCarouselConfiguration
GenuinSDK.shared.initializeEmbed(embedId: "YOUR_KEY", containerView: , viewConroller: self, embedConfiguration: embedConfiguration)
```
Check the additional information [here.](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#additional-information)
### Full Screen Embed
```swift ViewController.swift (With SSO) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbedFeed(embedId: "YOUR_EMBED_ID", containerView: , viewConroller: , ssoToken: , embedConfiguration: embedConfiguration)
```
```swift ViewController.swift (Without SSO) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbedFeed(embedId: "YOUR_EMBED_ID", containerView: , viewConroller: , embedConfiguration: embedConfiguration)
```
```swift ViewController.swift (With Contextual Parameters) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbedFeed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NO"], contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
**Note**: To fetch the Embed you need to add `YOUR_EMBED_ID`, `YOUR_CONTAINER_VIEW` in which you want the embed, and `YOUR_VIEW_CONTROLLER` containing your container view, while calling the above function. For auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN" in order to implement Embed with SSO in your app.
### Standard Wall Embed
```swift StandardWallFeedViewController.swift theme={null}
import GenuinSDK
class StandardWallFeedViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = true
GenuinSDK.shared.initializeStandardWall(embedId: "YOUR_EMBED_ID", containerView: self.view, viewConroller: self, embedConfiguration: embedConfiguration)
}
}
```
```
GenuinSDK.shared.initializeStandardWall(embedId: "YOUR_EMBED_ID", containerView: self.view, viewConroller: self, ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NO"], contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
**Note**: To fetch the Embed you need to add `YOUR_EMBED_ID` while calling the above function.
### Additional Information
To configure the `EmbedConfiguration` based on your need you can change the below values.
1. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
2. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
3. **interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
4. **genuinCarouselConfiguration** = This is an optional parameter. You can pass `GenuinCarouselConfiguration` object in this parameter. If `GenuinCarouselConfiguration` is provided then the carousel design will change accordingly. The default values are listed below, which you can pass in `GenuinCarouselConfiguration` object.
* `interTileSpacing` - spacing between the carousel's collection view items. It's default value is `8.0`
* `carouselInset` - edge insets for carousel's collection view. It's default value is `UIEdgeInsets(top: 8.0, left: 16.0, bottom: 0.0, right: 16.0)`
* `scrollDirection` - direction of carousel scroll. It's default value is `.horizontal`
* `aspectRatio` - define aspect ratio of carousel's collection view items. It's default value is `.ratio9x16`
* `tileCornerRadius` - cornerRadius for the carousel's collection view items. It's default value is `8.0`
Below are the optional parameters for the `params` key:
1. **name** - This is an optional string parameter. Pass this parameter for '`signup/login`'.
2. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
3. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
4. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
5. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
Below are the optional parameters for the `contextualParams` key:
1. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
2. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
3. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
**Note**: `lat` and `long` both parameters shall be passed in order to implement the contextual feed based on the location.
**Example**
```swift SSO Example theme={null}
GenuinSDK.shared.initializeEmbed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NUMBER"], embedConfiguration: embedConfiguration)
```
```swift Contextual Example theme={null}
GenuinSDK.shared.initializeEmbed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_TOKEN", contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
## Handle Login : via AutoLogin Approach
To Auto Login in the SDK, You need to call below method, whenever user is log in to your application.
**Note**: You don't need to call the below method if you have implemented the Embed With SSO already.
```swift ViewController.swift theme={null}
GenuinSDK.shared.ssoLogin(ssoToken: "YOUR_SSO_TOKEN")
```
**Handle AutoLogin in Embed**
```swift with embed theme={null}
GenuinSDK.shared.initializeEmbed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NO"], contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
```swift withtout embed theme={null}
GenuinSDK.shared.ssoLogin(ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME"])
```
```swift with completion handler theme={null}
GenuinSDK.shared.ssoLogin(ssoToken: "YOUR_SSO_TOKEN") { status in
}
// Where status of login = true or false
```
## Custom Login
If you want to handle login process as per your requirement then follow the below steps:
**Step 1**: Assign Delegate while initializing Genuin SDK
```swift Swift theme={null}
GenuinSDK.shared.delegate = self ( YOUR_CONTROLLER )
```
**Step 2**: Extend GenuinDelegate & Present your own controller on provided base controller
```swift Swift theme={null}
extension YOUR_CONTROLLER : GenuinDelegate{
func presentLoginViewController(baseViewController : UIViewController) {
guard let loginVC = GET AND ASSIGN YOUR CONTROLLER
baseViewController.present(loginVC, animated: true)
}
}
```
**Step 3**: Must call below login service from Genuin, to keep user logged in, in Genuin SDK.
```swift Swift theme={null}
GenuinSDK.shared.ssoLogin(ssoToken: "YOUR_SSO_TOKEN", params: ["name" : "FULL_NAME", "nickname" : "USER_NAME"])
```
## Handle Logout : via AutoLogin Approach
Whenever user logs out from your application call the below method.
```swift ViewController.swift theme={null}
GenuinSDK.shared.ssoLogout()
```
```swift with completion handler theme={null}
GenuinSDK.shared.ssoLogout { status in
}
// Where status of logout = true or false
```
## Handling Deep Link
**Note**: Make sure you have followed the installation steps in order to handle the deep links.
**Prerequisite**:
1. Make sure you have white labelled your community by following these [steps](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community)
2. Enable Associated Domains in Certificates, Identifiers & Profiles using your Apple Developer account at [https://developer.apple.com/account/resources/identifiers/list](https://developer.apple.com/account/resources/identifiers/list)
3. Create apple-app-site-association (without extension) file with following settings:
```json apple-app-site-association theme={null}
{"appclips":{"apps":["YOUR_TEAM_ID.APP_BUNDLE_ID.Clip"]},"applinks":{"apps":[],"details":[{"paths":["/*"],"appID":"YOUR_TEAM_ID.APP_BUNDLE_ID"}]}}
```
Once the file is created, host it on the white labeled domain at `https://YOUR_WHITE-LABELLED_DOMAIN/.well-known/apple-app-site-association`
4. Add Associated Domains in capabilities if not already,
Add applinks in domains, for Example:
applinks: `YOUR_WHITE-LABELLED_DOMAIN`
applinks: `www.YOUR_WHITE-LABELLED_DOMAIN`
To handle deep links in your app use the following methods.
```swift SceneDelegate.swift theme={null}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
handleGenuinDeeplink(deeplinkURL: connectionOptions.userActivities.first?.webpageURL)
}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
//redirect if genuin SDK handles the deeplink
handleGenuinDeeplink(deeplinkURL: userActivity.webpageURL)
}
func handleGenuinDeeplink(deeplinkURL: URL?) {
if let dlURL = deeplinkURL, GenuinSDK.shared.willHandleDeepLink(url: dlURL){
GenuinSDK.initDeeplinkWith(url: dlURL)
if let rootVC = window?.rootViewController as? UIViewController{
DispatchQueue.main.async {
GenuinSDK.shared.handleDeeplink(viewController: rootVC)
}
}
}
}
}
```
```swift AppDelegate.swift theme={null}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
//redirect if genuin SDK handles the deeplink
if let dlURL = userActivity.webpageURL , GenuinSDK.shared.willHandleDeepLink(url: dlURL){
GenuinSDK.initDeeplinkWith(url: dlURL)
if let rootVC = window?.rootViewController as? UIViewController {
GenuinSDK.shared.handleDeeplink(viewController: rootVC)
}
}
return true
}
```
**Note**: `GenuinSDK.shared.willHandleDeepLink(url: dlURL)` function will check whether `GenuinSDK` will handle the given deeplink or not. You can use it according to your deeplink redirection flow.
### Instructions for `SceneDelegate`:
1. In `SceneDelegate.swift`, implement the `scene(_:continue:)` method.
2. Notify the SDK of the continued scene via `GenuinSDK.initDeeplinkWith(url: dlURL)`.
3. Handle deep links using the root view controller by calling `GenuinSDK.shared.handleDeeplink(viewController: rootVC)`.
**NOTE**: To handle redirection of the deeplink , it is mandatory to call `GenuinSDK.initDeeplinkWith(url: dlURL)`
### Instructions for `AppDelegate`:
1. In `AppDelegate.swift`, implement the `application(_:continue:restorationHandler:)` method.
2. Notify the SDK of the continued scene via `GenuinSDK.initDeeplinkWith(url: dlURL)`.
3. Use `GenuinSDK.shared.handleDeeplink(viewController: rootVC)` to manage the deep link using the app's root view controller.
**Note**:
1. To handle the Deeplink from another controller call the `GenuinSDK.shared.handleDeeplink(viewController: vc)` function from specific controller
2. If you are following the `SceneDelegate` method then calling this `GenuinSDK.shared.handleDeeplink(viewController: self)` function is mandatory
```swift theme={null}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
GenuinSDK.shared.handleDeeplink(viewController: self)
}
```
## Handling Push Notifications
### Using Firebase
1. Create an app in your firebase console by following [these steps](https://firebase.google.com/docs/cloud-messaging/ios/client)
2. Download the `GoogleService-Info.plist` file and add it in xcode project
3. Add pod in pod file
```swift podfile theme={null}
pod 'FirebaseMessaging', '~> 10.24.0'
```
4. To enable the push notifications functionality then enable the Push Notifications in your target. To do so, `Select the target > Signing & Capabilities > Add Capability of Push Notification`
5. Import
```swift Swift theme={null}
import FirebaseMessaging
import GenuinSDK
```
AppDelegate
```swift AppDelegate.swift theme={null}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
//Assign APNS token and notify sdk
Messaging.messaging().apnsToken = deviceToken
GenuinSDK.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken, isFCMIntegrated: true)
}
```
**Note**: Pass `true` value in `isFCMIntegrated` parameter, as we are using the Firebase.
6. Initialize
SceneDelegate
```swift SceneDelegate.swift theme={null}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
//Register the notification
registerForNotification()
//configure firebase
FirebaseApp.configure()
//set delegate , extend current class with MessagingDelegate
Messaging.messaging().delegate = self
}
```
7. Place this code to take the user permission for Push Notification
```swift SceneDelegate.swift theme={null}
func registerForNotification(){
//Take permission and register remote notification
let current = UNUserNotificationCenter.current()
current.getNotificationSettings(completionHandler: { (settings) in
if settings.authorizationStatus == .notDetermined{
self.requestForNotificationPermission()
}else if settings.authorizationStatus == .authorized {
UNUserNotificationCenter.current().delegate = self
DispatchQueue.main.async{
UIApplication.shared.registerForRemoteNotifications()
}
}
})
}
private func requestForNotificationPermission(){
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in
print(granted)
}
UIApplication.shared.registerForRemoteNotifications()
}
```
8. Extend `MessagingDelegate` and Add follwing method:
```swift SceneDelegate.swift theme={null}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
if let token = fcmToken {
//fetch and register token
getInstanceID()
}
}
func getInstanceID(){
Messaging.messaging().token { token, error in
// Check for error. Otherwise do what you will with token here
if let error = error {
print("Error fetching remote instance ID: \(error)")
} else if let result = token {
print("Remote instance ID token: \(result)")
GenuinSDK.shared.registerFCMToken(token: result)
}
}
}
```
9. To Handle the Push Notification Redirection whenever the user taps, follow the below code
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if let userInfo = response.notification.request.content.userInfo as? [String: AnyObject]{
//notify firebase
Messaging.messaging().appDidReceiveMessage(userInfo)
//check if genuin will handle notification
if GenuinSDK.shared.willHandleNotification(userInfo: userInfo){
//notify to redirect
GenuinSDK.shared.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler)
//notification notification
if let rootVC = window?.rootViewController as? UIViewController{
GenuinSDK.shared.handleNotifications(viewController: rootVC)
}
}
}
}
```
**Note**: `GenuinSDK.shared.willHandleNotification(userInfo: userInfo)` function will check whether `GenuinSDK` will handle the given notification or not. You can use it according to your notification redirection flow.
10. To configure notification UI
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
print("\(userInfo)")
//mention design type for notification
completionHandler([.list, .badge, .sound])
}
```
11. If you want to handle the notification when app is opened then follow the below code
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
GenuinSDK.shared.userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler)
if let rootVC = window?.rootViewController as? UIViewController{
GenuinSDK.shared.handleNotifications(viewController: rootVC)
}
//mention design type for notification
completionHandler([.list, .badge, .sound])
}
```
**Note**: To handle the notification from another controller call the `GenuinSDK.shared.handleNotifications(viewController: YOUR_VIEW_CONTROLLER)` function
### Using APNS
1. To enable the push notifications functionality then enable the Push Notifications in your target. To do so, `Select the target > Signing & Capabilities > Add Capability of Push Notification`
2. Import
```swift Swift theme={null}
import GenuinSDK
```
AppDelegate
```swift AppDelegate.swift theme={null}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
//Assign APNS token and notify sdk
GenuinSDK.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken, isFCMIntegrated: false)
}
```
**Note**: Pass `false` value in `isFCMIntegrated` parameter, as we are not using the Firebase.
SceneDelegate
Initialize
```swift SceneDelegate.swift theme={null}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
//Register the notification
registerForNotification()
}
```
3. Place this code to take the user permission for Push Notification
```swift SceneDelegate.swift theme={null}
func registerForNotification(){
//Take permission and register remote notification
let current = UNUserNotificationCenter.current()
current.getNotificationSettings(completionHandler: { (settings) in
if settings.authorizationStatus == .notDetermined{
self.requestForNotificationPermission()
}else if settings.authorizationStatus == .authorized {
UNUserNotificationCenter.current().delegate = self
DispatchQueue.main.async{
UIApplication.shared.registerForRemoteNotifications()
}
}
})
}
private func requestForNotificationPermission(){
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in
print(granted)
}
UIApplication.shared.registerForRemoteNotifications()
}
```
4. To Handle the Push Notification Redirection whenever the user taps, follow the below code
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if let userInfo = response.notification.request.content.userInfo as? [String: AnyObject]{
//check if genuin will handle notification
if GenuinSDK.shared.willHandleNotification(userInfo: userInfo){
//notify to redirect
GenuinSDK.shared.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler)
//notification notification
if let rootVC = window?.rootViewController as? UIViewController{
GenuinSDK.shared.handleNotifications(viewController: rootVC)
}
}
}
}
```
**Note**: `GenuinSDK.shared.willHandleNotification(userInfo: userInfo)` function will check whether `GenuinSDK` will handle the given notification or not. You can use it according to your notification redirection flow.
5. To configure notification UI
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
print("\(userInfo)")
//mention design type for notification
completionHandler([.list, .badge, .sound])
}
```
6. If you want to handle the notification when app is opened then follow the below code
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
GenuinSDK.shared.userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler)
if let rootVC = window?.rootViewController as? UIViewController{
GenuinSDK.shared.handleNotifications(viewController: rootVC)
}
//mention design type for notification
completionHandler([.list, .badge, .sound])
}
```
**Note**: To handle the notification from another controller call the `GenuinSDK.shared.handleNotifications(viewController: YOUR_VIEW_CONTROLLER)` function.
## What’s next?
Integrate Android SDK in Your ecosystem.
Integrate Web SDK in your ecosystem.
Integrate React Native SDK in your ecosystem.
## Support
If you need any assistance or have any questions, feel free to email us at [support@begenuin.com](mailto:support@begenuin.com).
# iOS SDK 2.0
Source: https://resources.begenuin.com/developers/sdk-docs/ios_sdk_2.0
Genuin iOS SDK comprises features such as brand feed, communities, and groups.
| SDK | Description |
| ------------ | ------------------------------------------------------------------------------------------------- |
| GenuinCore | Includes the core functionality of the Genuin Ecosystem: Embeds and User authentication. |
| GenuinUI | Additional UI flows like comments, search, deep-links, notifications, group/community detail etc. |
| GenuinCamera | Camera flows for video content creation. |
| GenuinAI | Additional flows for AI assisted community/group creation. |
## Requirements
| Platform | Minimum Deployment Target | Language | Supported Orientations | Supported Destinations |
| -------- | ------------------------- | -------- | ---------------------- | ---------------------- |
| iOS | 13.0 | Swift | Portrait | iPhone |
## Permissions (Optional)
Permissions to be added in `info.plist` file of your application
| Permission | Usage | Used Where | In SDK |
| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ------------ |
| Camera (NSCameraUsageDescription) | Genuin needs permissions to open your camera and microphone. This allows Genuin to record videos that can be shared with other people. | Post, Video Comment | GenuinCamera |
| Microphone (NSMicrophoneUsageDescription) | Genuin needs permissions to open your camera and microphone. This allows Genuin to record videos that can be shared with other people. | Post, Voice Comment | GenuinCamera |
| Photos (NSPhotoLibraryUsageDescription) | Genuin needs permissions to access your photo library. This allows Genuin to download videos to your phone and save it to your library. | Post, Profile, Banner | GenuinCore |
| Speech Recognition (NSSpeechRecognitionUsageDescription) | The transcript of your recording will be displayed to you in the end for you to overlay it on the audio message. | To generate transcript from recorded audio | GenuinCamera |
| Contacts (NSContactsUsageDescription) | Genuin requires to sync with your contacts and provide a better experience when you wish to share your posts with them. | Add Members in Communities and Groups | GenuinUI |
| Location (NSLocationWhenInUseUsageDescription) | Your precise location will help us suggest your community details more accurately. | AI Powered Communities based on the User Location | GenuinCore |
| Tracking (NSUserTrackingUsageDescription) | Your data will be used to analyse ads we run! | Monetization | GenuinCore |
If any permission is not given then that particular feature will not be accessible in your app.
## Installation
### Using Swift Package Manager (SPM)
To add Genuin SDK to your iOS project via Swift Package Manager:
**1. In Xcode, go to:**
File > Swift Packages > Add Package Dependency
**2. When prompted, enter the Genuin SDK repository URL:**
```swift Repository URL theme={null}
https://github.com/genuininc/genuin_ios_sdk
```
**3. Choose the version:**
```swift Version theme={null}
Version: 2.1.1
```
**Note:** Make sure all Genuin SDK modules are added with the same version (2.1.1) for compatibility.
**Module Dependency Structure**
The Genuin SDK is composed of multiple interdependent modules. These follow a linear dependency chain as outlined below:
```
ai ← camera ← ui ← core
```
**Integration Rules**
1. core - Can be used independently. It is the foundation for all other modules.
2. ui - Requires core. Must be added together.
3. camera - Requires both core and ui.
4. ai - Requires camera, ui, and core.
Ensure modules are added in the correct order and with the same version to avoid conflicts during build and runtime.
### Using Cocoapods
If your project doesn't have the CocoaPods setup then start with `pod init` which will create the Podfile, else do following changes in the pod file to install GenuinSDK.
```swift In Podfile theme={null}
platform :ios, '13.0'
target 'YourProject' do
use_frameworks!
# Pods for YourProject
genuin_sdk_version = '2.1.1'
pod "GenuinCore", :git => "https://github.com/genuininc/genuin_ios_sdk.git", :tag => genuin_sdk_version
pod "GenuinUI", :git => "https://github.com/genuininc/genuin_ios_sdk.git", :tag => genuin_sdk_version
pod "GenuinCamera", :git => "https://github.com/genuininc/genuin_ios_sdk.git", :tag => genuin_sdk_version
pod "GenuinAI", :git => "https://github.com/genuininc/genuin_ios_sdk.git", :tag => genuin_sdk_version
end
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'Giphy'
`xcrun -sdk iphoneos bitcode_strip -r Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK -o Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK`
end
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
```
**a. For Core SDK:**
```swift In Podfile theme={null}
pod "GenuinCore", :git => "https://github.com/genuininc/genuin_ios_sdk.git", :tag => genuin_sdk_version
```
**b. For UI SDK:**
```swift In Podfile theme={null}
pod "GenuinUI", :git => "https://github.com/genuininc/genuin_ios_sdk.git", :tag => genuin_sdk_version
```
**c. For Camera SDK:**
```swift In Podfile theme={null}
pod "GenuinCamera", :git => "https://github.com/genuininc/genuin_ios_sdk.git", :tag => genuin_sdk_version
```
**d. For AI SDK:**
```swift In Podfile theme={null}
pod "GenuinAI", :git => "https://github.com/genuininc/genuin_ios_sdk.git", :tag => genuin_sdk_version
```
**Example**
Import the GenuinSDK module in your `SceneDelegate/AppDelegate`.
```swift SceneDelegate.swift theme={null}
import GenuinCore
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Optional configuration and attaching the UIWindow to UIWindowScene
guard let _ = (scene as? UIWindowScene) else { return }
// Initialize the SDK configuration
let configuration = GenuinConfiguration.shared
// For Production environment (Default)
configuration.setCustomLoader("YOUR_LOADER", bundle: .main)
// For QA Environment
configuration.environment = .qa
// Initialize the SDK with your API key and configuration
GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)
// Notify the SDK that the scene will connect
GenuinSDK.shared.scene(scene, willConnectTo: session, options: connectionOptions)
}
```
```swift AppDelegate.swift theme={null}
import GenuinCore
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize the SDK configuration
let configuration = GenuinConfiguration.shared
// For Production Environment (Default)
configuration.setCustomLoader("YOUR_LOADER", bundle: .main)
// For QA Environment
configuration.environment = .qa
// Initialize the SDK with your API key and configuration
GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)
return true
}
```
Cocoapods (with all sdk initialize)
```swift theme={null}
GenuinUI.shared.initialize() //Initialize method is required if GenuinUI sdk is integrated
GenuinCamera.shared.initialize() //Initialize method is required if GenuinCamera sdk is integrated
GenuinAI.shared.initialize() //Initialize method is required if GenuinAI sdk is integrated
GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)
```
To load your lottie animation accross the Genuin SDK, you can add it here `configuration.setCustomLoader("YOUR_LOADER", bundle: .main)`
### Instructions for `SceneDelegate`:
1. Ensure you are using the `UISceneDelegate` in your app.
2. In your `SceneDelegate.swift` file, implement the `scene(_:willConnectTo:options:)` method.
3. Use the shared configuration and set up any custom loaders or additional parameters.
4. Call `GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)` with your API key and the configured options.
5. Ensure that `GenuinSDK.shared.scene(scene, willConnectTo: session, options: connectionOptions)` is called to notify the SDK of the scene connection.
### Instructions for `AppDelegate`:
1. In your `AppDelegate.swift`, implement the `application(_:didFinishLaunchingWithOptions:)` method.
2. Set up the shared configuration and initialize the SDK with your API key.
3. Call `GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)` with your API key and the configured options.
4. Return `true` to indicate successful launch configuration.
```swift In SceneDelegate.swift theme={null}
import GenuinCore
import GenuinUI
import GenuinCamera
import GenuinAI
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Optional configuration and attaching the UIWindow to UIWindowScene
guard let _ = (scene as? UIWindowScene) else { return }
// Initialize the SDK configuration
let configuration = GenuinConfiguration.shared
// For Production environment (Default)
configuration.setCustomLoader("YOUR_LOADER", bundle: .main)
// For QA Environment
configuration.environment = .qa
GenuinUI.shared.initialize() //Initialize method is required if GenuinUI sdk is integrated
GenuinCamera.shared.initialize() //Initialize method is required if GenuinCamera sdk is integrated
GenuinAI.shared.initialize() //Initialize method is required if GenuinAI sdk is integrated
// Initialize the SDK with your API key and configuration
GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)
}
```
```swift In AppDelegate.swift theme={null}
import GenuinCore
import GenuinUI
import GenuinCamera
import GenuinAI
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize the SDK configuration
let configuration = GenuinConfiguration.shared
// For Production Environment (Default)
configuration.setCustomLoader("YOUR_LOADER", bundle: .main)
// For QA Environment
configuration.environment = .qa
GenuinUI.shared.initialize() //Initialize method is required if GenuinUI sdk is integrated
GenuinCamera.shared.initialize() //Initialize method is required if GenuinCamera sdk is integrated
GenuinAI.shared.initialize() //Initialize method is required if GenuinAI sdk is integrated
// Initialize the SDK with your API key and configuration
GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)
return true
}
```
### Instructions for `SwiftUI`:
In your SwiftUI’s App file initialize the GenuinSDK as follows:
```swift theme={null}
import SwiftUI
import GenuinCore
import GenuinUI
import GenuinAI
import GenuinCamera
@main
struct GenuinSwiftUIApp: App {
init() {
let configuration = GenuinConfiguration()
// For QA Environment
configuration.environment = .qa
configuration.setCustomLoader("YOUR_LOADER", bundle: Bundle.main)
GenuinUI.shared.initialize()
GenuinCamera.shared.initialize()
GenuinAI.shared.initialize()
GenuinSDK.shared.initialize(apiKey: "YOUR_API_KEY", configuration: configuration)
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
```
**Note**: Our SDK is well optimized for `iOS version 15.0` and above, but if you are using `iOS version 13` or `14` then put this `if #available(iOS 15.0, *)` condition while importing the GenuinSDK.
## Monetization
To enable Monetization use following code snippet to get **advertisingIdentifier** by **AppTrackingTranspancy**. You need to add `NSUserTrackingUsageDescription` in `Info.plist` as described [here](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#permissions-optional).
```swift For SceneDelegate theme={null}
import AppTrackingTransparency
import AdSupport //Import only if you want to use advertisingIdentifier
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
DispatchQueue.main.async {
ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .notDetermined:
break
case .restricted:
break
case .denied:
break
case .authorized:
// If you want to check the current advertisingIdentifier
print("advertisingIdentifier: ", ASIdentifierManager.shared().advertisingIdentifier.uuidString)
break
@unknown default:
break
}
}
}
}
}
```
```swift For AppDelegate theme={null}
import AppTrackingTransparency
import AdSupport //Import only if you want to use advertisingIdentifier
class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationDidBecomeActive(_ application: UIApplication) {
DispatchQueue.main.async {
ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .notDetermined:
break
case .restricted:
break
case .denied:
break
case .authorized:
// If you want to check the current advertisingIdentifier
print("advertisingIdentifier: ", ASIdentifierManager.shared().advertisingIdentifier.uuidString)
break
@unknown default:
break
}
}
}
}
}
```
Also if you enable monetization then you need to update App Privacy in AppStoreConnect
**Need to declare in App Store Connect that your app is using Advertising Data**
Steps:
* **Log in** to your App Store Connect.
* **Select the app** you are working on.
* Go to App **Privacy > Data Collection**.
* Find the Usage Data section and select the **Advertising Data**.
* Click on **Save/Publish**.
* Now Setup Advertising Data by selecting (Third-Party Advertising, Analytics, Product Personalization, App Functionality, Other Purposes)
* Click on **Next** and give the answers as asked.
* Click on **save**.
## Embed with Swift
**Note**: Make sure you have followed the [installation steps](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#installation) in order to implement the Carousel Embed.
**Note**: In order to migrate from GenuinSDK 1.0 to 2.0, you need to replace `import GenuinSDK` to `import GenuinCore` in your codebase.
### Carousel Embed
Refer to [Carousel View](https://resources.begenuin.com/developers/guides/embed#mobile-view) in Mobile
We have introduced new attribute `GenuinEmbedAttributes` that holds all the required data attributes needed to create and initialize an embed.
You can initialize it with the following parameters:
```swift ViewController.swift theme={null}
init(
embedId: String,
uniqueId: String? = nil,
viewController: UIViewController,
ssoToken: String? = nil,
params: [String: Any]? = nil,
contextualParams: [String: Any]? = nil,
embedConfiguration: EmbedConfiguration = EmbedConfiguration()
)
```
Parameters
* `embedId: String` – The identifier for the embed.
* `uniqueId: String?` (optional) – A unique identifier, if needed.
* `viewController: UIViewController` – The parent view controller for presenting the embed.
* `ssoToken: String?` (optional) – Single Sign-On token for authentication.
* `params: [String: Any]?` (optional) – Additional parameters for customization.
* `contextualParams: [String: Any]?` (optional) – Context-specific parameters for the embed.
* `embedConfiguration: EmbedConfiguration` (optional) – Configuration object for customizing embed behavior. Defaults to a new EmbedConfiguration instance.
Creating and Loading an Embed
You can create and load a GenuinEmbedView in following ways:
#### Approach 01
```swift ViewController.swift (With SSO) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbed(embedId: "YOUR_EMBED_ID", containerView: , viewConroller: , ssoToken: , embedConfiguration: embedConfiguration)
```
```swift ViewController.swift (Without SSO) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbed(embedId: "YOUR_EMBED_ID", containerView: , viewConroller: , embedConfiguration: embedConfiguration)
```
```swift ViewController.swift (With Contextual Parameters) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NO"], contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
**Note**: To fetch the Embed you need to add `YOUR_EMBED_ID`, `YOUR_CONTAINER_VIEW` in which you want the embed, and `YOUR_VIEW_CONTROLLER` containing your container view, while calling the below function. For auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN" in order to implement Embed with SSO in your app.
#### Approach 02
Initialize with Attributes During Creation
Create the `GenuinEmbedAttributes` first, then pass it directly while initializing the embed view:
```swift ViewController.swift theme={null}
// Below is an Example Code
let attributes = GenuinEmbedAttributes(embedId: YOUR_EMBED_ID, viewController: YOUR_VIEW_CONTROLLER)
let embedView = GenuinEmbedView(attributes: attributes)
self.YOUR_VIEW.addSubview(embedView)
embedView.fetchDataAndLoad()
```
#### Approach 03
Initialize First, Then Set Attributes
Create the embed view first and assign the attributes afterward:
```swift ViewController.swift theme={null}
// Below is an Example Code
let embedView = GenuinEmbedView()
let attributes = GenuinEmbedAttributes(embedId: YOUR_EMBED_ID, viewController: YOUR_VIEW_CONTROLLER)
embedView.initWith(attributes: attributes)
self.YOUR_VIEW.addSubview(embedView)
embedView.fetchDataAndLoad()
```
#### Approach 04
Adding the Embed View in a Storyboard
Steps:
1. When using **Interface Builder**, first create a wrapper view with your preferred height and constraints. This wrapper will serve as the container for the `GenuinEmbedView`.
2. Drag a `UIView` for embed and add it inside your wrapper view.
3. Set the embed view’s class to `GenuinEmbedView` in the Identity Inspector.
4. If a module for the specified class does not appear , then set the module as `GenuinCore` in the module field below the class.
5. Connect it to an `@IBOutlet` in your view controller (e.g., `embedView`).
6. Example: Initialize and Load with an Outlet
```swift ViewController.swift theme={null}
@IBOutlet weak var embedView: GenuinEmbedView?
func loadEmbed() {
//specify your attributes
let attributes = GenuinEmbedAttributes(embedId: YOUR_EMEBED_ID,
viewController: YOUR_VIEW_CONTROLLER)
embedView?.initWith(attributes: attributes)
embedView?.fetchDataAndLoad()
}
```
7. Call `loadEmbed()` to initialize and load the embed.
Check the additional information [here.](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#additional-information)
### Full Screen Embed
```swift ViewController.swift (With SSO) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbedFeed(embedId: "YOUR_EMBED_ID", containerView: , viewConroller: , ssoToken: , embedConfiguration: embedConfiguration)
```
```swift ViewController.swift (Without SSO) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbedFeed(embedId: "YOUR_EMBED_ID", containerView: , viewConroller: , embedConfiguration: embedConfiguration)
```
```swift ViewController.swift (With Contextual Parameters) theme={null}
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = false
embedConfiguration.isDirectDeepLinkEnabled = false
GenuinSDK.shared.initializeEmbedFeed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NO"], contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
**Note**: To fetch the Embed you need to add `YOUR_EMBED_ID`, `YOUR_CONTAINER_VIEW` in which you want the embed, and `YOUR_VIEW_CONTROLLER` containing your container view, while calling the above function. For auto login in the SDK, you shall pass "YOUR\_SSO\_TOKEN" in order to implement Embed with SSO in your app.
### Standard Wall Embed
```swift StandardWallFeedViewController.swift theme={null}
import GenuinCore
class StandardWallFeedViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let embedConfiguration = EmbedConfiguration()
embedConfiguration.isShowProfileEnabled = true
GenuinSDK.shared.initializeStandardWall(embedId: "YOUR_EMBED_ID", containerView: self.view, viewConroller: self, embedConfiguration: embedConfiguration)
}
}
```
```
GenuinSDK.shared.initializeStandardWall(embedId: "YOUR_EMBED_ID", containerView: self.view, viewConroller: self, ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NO"], contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
**Note**: To fetch the Embed you need to add `YOUR_EMBED_ID` while calling the above function.
## Embed with SwiftUI
### Carousel Embed
Refer to [Carousel View](https://resources.begenuin.com/developers/guides/embed#mobile-view) in Mobile
Genuin Carousel Embed View Wrapper
```swift Basic Embed theme={null}
import SwiftUI
import UIKit
import GenuinCore
struct GenuinCarouselViewWrapper: UIViewRepresentable {
var embedId: String
func makeUIView(context: Context) -> UIView {
let container = UIView()
return container
}
func updateUIView(_ uiView: UIView, context: Context) {
DispatchQueue.main.async {
guard let parentVC = uiView.parentViewController else {
print("Could not get parent VC!")
return
}
let embedConfiguration = EmbedConfiguration()
GenuinSDK.shared.initializeEmbed(
embedId: embedId,
containerView: uiView,
viewConroller: parentVC,
embedConfiguration: embedConfiguration
)
}
}
}
```
```swift Embed with Customization & SSO theme={null}
import SwiftUI
import UIKit
import GenuinCore
struct GenuinCarouselContextViewWrapper: UIViewRepresentable {
var embedId: String
var uniqueId: String?
var ssoToken: String?
var params: [String : Any]?
var contextualParams: [String: Any]?
var embedConfiguration: EmbedConfiguration = EmbedConfiguration()
func makeUIView(context: Context) -> UIView {
let container = UIView()
return container
}
func updateUIView(_ uiView: UIView, context: Context) {
DispatchQueue.main.async {
guard let parentVC = uiView.parentViewController else {
print("Could not get parent VC!")
return
}
GenuinSDK.shared.initializeEmbed(
embedId: embedId,
uniqueId: uniqueId,
containerView: uiView,
viewConroller: parentVC,
ssoToken: ssoToken,
params: params,
contextualParams: contextualParams,
embedConfiguration: embedConfiguration
)
}
}
}
```
Example Usage
```swift Basic Embed theme={null}
import SwiftUI
struct CarouselView: View {
var body: some View {
VStack {
GenuinCarouselViewWrapper(embedId: "YOUR_EMBED_ID")
.frame(height: 200)
Spacer()
}
}
}
#Preview {
CarouselView()
}
```
```swift Embed with Customization & SSO theme={null}
import SwiftUI
import UIKit
import GenuinCore
struct CarouselContextView: View {
@State private var contextualParams: [String: Any]? = nil
@State private var txtContext: String = ""
private var embedConfiguration: EmbedConfiguration = EmbedConfiguration()
init() {
let genuinCarouselConfiguration = GenuinCarouselConfiguration()
genuinCarouselConfiguration.aspectRatio = .ratio4x5
embedConfiguration.genuinCarouselConfiguration = genuinCarouselConfiguration
}
var body: some View {
VStack {
GenuinCarouselContextViewWrapper(embedId: "YOUR_EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NO"], contextualParams: contextualParams, embedConfiguration: embedConfiguration)
.frame(height: 200)
HStack {
TextField("Contextual Params", text: $txtContext)
.textFieldStyle(.roundedBorder)
Button("Assign Context") {
contextualParams = ["page_context": txtContext, "geo" : [ "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE ]]
}
}
.padding()
Spacer()
}
}
}
#Preview {
CarouselContextView()
}
```
### Standard Wall Embed
Standard Wall View Wrapper
```swift Basic Embed theme={null}
import SwiftUI
import GenuinCore
struct GenuinSDKStandardWallNavigationControllerWrapper: UIViewControllerRepresentable {
var embedId: String
func makeUIViewController(context: Context) -> UINavigationController {
// Return the UIKit UINavigationController from the SDK
let embedConfiguration = EmbedConfiguration()
return GenuinSDK.shared.getStandardWallController(embedId: embedId, embedConfiguration: embedConfiguration) ?? UINavigationController()
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
// No update logic needed unless the SDK content needs to change dynamically
}
}
```
Example Usage
```swift Basic Embed theme={null}
import SwiftUI
struct StandardWallView: View {
var body: some View {
GenuinSDKStandardWallNavigationControllerWrapper(embedId: "YOUR_EMBED_ID")
.edgesIgnoringSafeArea(.top)
}
}
#Preview {
StandardWallView()
}
```
**Note**: To fetch the Embed you need to add `YOUR_EMBED_ID` while calling the above function.
### Additional Information
To configure the `EmbedConfiguration` based on your need you can change the below values.
1. **isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
2. **isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter "**interactionDeepLink**" will be ignored. If not passed then the regular flow will work.
3. **interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
4. **genuinCarouselConfiguration** = This is an optional parameter. You can pass `GenuinCarouselConfiguration` object in this parameter. If `GenuinCarouselConfiguration` is provided then the carousel design will change accordingly. The default values are listed below, which you can pass in `GenuinCarouselConfiguration` object.
* `interTileSpacing` - spacing between the carousel's collection view items. It's default value is `8.0`
* `viewInset` - edge insets for carousel's collection view. It's default value is `UIEdgeInsets(top: 8.0, left: 16.0, bottom: 0.0, right: 16.0)`
* `tileCornerRadius` - cornerRadius for the carousel's collection view items. It's default value is `8.0`
Below are the optional parameters for the `params` key:
1. **name** - This is an optional string parameter. Pass this parameter for '`signup/login`'.
2. **mobile** - This is an optional string parameter. Pass this parameter for `signup/login`.
3. **email** - This is an optional string parameter. Pass this parameter for `signup/login`.
4. **nickname** - This is an optional string parameter. If nickname is available in genuin ecosystem it will be used, else genuin will generate of its own.
5. **profile\_image**: This is an optional string parameter. Pass the `profile_image` parameter if you want to show the profile image in the SDK.
Below are the optional parameters for the `contextualParams` key:
1. **page\_context** - This is an optional string parameter. Pass this parameter for '`context`', so that feed could load based on that context.
2. **lat** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the latitude and context.
3. **long** - This is an optional float parameter. Pass this parameter in `geo` so that the feed could load based on the longitude and context.
**Note**: `lat` and `long` both parameters shall be passed in order to implement the contextual feed based on the location.
**Example**
```swift SSO Example theme={null}
GenuinSDK.shared.initializeEmbed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NUMBER"], embedConfiguration: embedConfiguration)
```
```swift Contextual Example theme={null}
GenuinSDK.shared.initializeEmbed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_TOKEN", contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
**Note**: You can pass above parameters in `GenuinEmbedAttributes` as well
## Placement with Swift
**Note**: Make sure you have followed the [installation steps](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#installation) in order to implement the Carousel Embed.
**Note**: In order to migrate from GenuinSDK 1.0 to 2.0, you need to replace `import GenuinSDK` to `import GenuinCore` in your codebase.
GenuinPlacementAttributes
We have introduced new attribute `GenuinPlacementAttributes` which is used to hold all the necessary data for creating and initializing a placement view.
You can initialize it with the following parameters:
```swift ViewController.swift theme={null}
init(
placementId: String,
styleId: String,
uniqueId: String? = nil,
viewController: UIViewController,
ssoToken: String? = nil,
params: [String: Any]? = nil,
contextualParams: [String: Any]? = nil,
placementConfiguration: PlacementConfiguration = PlacementConfiguration()
)
```
Parameters
* `placementId: String` – Identifier for the placement.
* `styleId: String` – Identifier for the placement style.
* `uniqueId: String?` (optional) – Unique identifier for this placement instance.
* `viewController: UIViewController` – Parent view controller that will present the placement.
* `ssoToken: String?` (optional) – Single Sign-On token for authentication.
* `params: [String: Any]?` (optional) – Additional parameters to customize the placement.
* `contextualParams: [String: Any]?` (optional) – Context-specific parameters for the placement.
* `placementConfiguration: PlacementConfiguration` (optional) – Custom configuration object. Defaults to a new instance of PlacementConfiguration.
Creating and Loading an Placement
You can create and load a `GenuinPlacementView` in following ways:
#### Approach 01
Initialize placement
```swift ViewController.swift theme={null}
let placementConfiguration = PlacementConfiguration()
GenuinSDK.shared.initializePlacement(
placementId: "PLACEMENT_ID",
styleId: "STYLE_ID",
containerView: YOUR_CONTAINER_VIEW,
viewController: YOUR_CONTROLLER,
contextualParams: [
"page_context": "",
"geo": [
"lat": XX.XXX, // Float or Double
"long": XX.XXX, // Float or Double
"radius_limit": // Int
],
"place": [
"country": "",
"state": "",
"city": "",
"zipcode": // Int
],
"time": , // Long
"user_segments": [
"age": "",
"min_age": "",
"max_age": "",
"segment": "",
"gender": "M/F/O",
"race": ""
],
"url": "https://url/",
"brands_ids": [
brandId1, // Int
brandId2 // Int
],
"user_interests": [""],
"posted_by_user_ids": [
"user_id1",
"user_id2"
],
"previous_page_context": "",
"user_context": ""
],
placementConfiguration: placementConfiguration
)
```
#### Approach 02
Initialize with Attributes During Creation
Create the `GenuinPlacementAttributes` first, then pass it directly while initializing the placement view:
```swift ViewController.swift theme={null}
let attributes = GenuinPlacementAttributes(
placementId: "YOUR_PLACEMENT_ID",
styleId: "YOUR_PLACEMENT_STYLE_ID",
viewController: YOUR_VIEW_CONTROLLER
)
let placementView = GenuinPlacementView(attributes: attributes)
self.YOUR_VIEW.addSubview(placementView)
placementView.fetchDataAndLoad()
```
#### Approach 03
Initialize First, Then Set Attributes
Create the placement view first and assign the attributes afterward:
```swift ViewController.swift theme={null}
let placementView = GenuinPlacementView()
let attributes = GenuinPlacementAttributes(
placementId: "YOUR_PLACEMENT_ID",
styleId: "YOUR_PLACEMENT_STYLE_ID",
viewController: YOUR_VIEW_CONTROLLER
)
placementView.initWith(attributes: attributes)
self.YOUR_VIEW.addSubview(placementView)
placementView.fetchDataAndLoad()
```
#### Approach 04
Adding the Placement View in a Storyboard
Steps:
1. When using **Interface Builder**, first create a wrapper view with your preferred height and constraints. This wrapper will serve as the container for the `GenuinPlacementView`.
2. Drag a `UIView` for placement and add it inside your wrapper view.
3. Set the placement view’s class to `GenuinPlacementView` in the Identity Inspector.
4. If a module for the specified class does not appear , then set the module as `GenuinCore` in the module field below the class.
5. Connect it to an `@IBOutlet` in your view controller (e.g., `placementView`).
6. Example: Initialize and Load with an Outlet
```swift ViewController.swift theme={null}
@IBOutlet weak var placementView: GenuinPlacementView?
func loadPlacement() {
let attributes = GenuinPlacementAttributes(
placementId: "YOUR_PLACEMENT_ID",
styleId: "YOUR_PLACEMENT_STYLE_ID",
viewController: YOUR_VIEW_CONTROLLER
)
placementView?.initWith(attributes: attributes)
placementView?.fetchDataAndLoad()
}
```
7. Call `loadPlacement()` to initialize and load the placement.
## Loading Embed and Placement Views in the Background
You can fetch data for an embed or placement view in the background as per your requirement and add it to your view hierarchy once the data is ready.
### Example: Loading an Embed in the Background
```swift ViewController.swift theme={null}
let embedView = GenuinEmbedView()
let attributes = GenuinEmbedAttributes(
embedId: YOUR_EMBED_ID,
viewController: YOUR_VIEW_CONTROLLER
)
embedView.initWith(attributes: attributes)
embedView.fetchDataInBackground { success in
if success {
self.YOUR_VIEW.addSubview(embedView)
embedView.load()
}
}
```
### Example: Loading a Placement in the Background
```swift ViewController.swift theme={null}
let placementView = GenuinPlacementView()
let attributes = GenuinPlacementAttributes(
placementId: "YOUR_PLACEMENT_ID",
styleId: "YOUR_PLACEMENT_STYLE_ID",
viewController: YOUR_VIEW_CONTROLLER
)
placementView.initWith(attributes: attributes)
placementView.fetchDataInBackground { success in
if success {
self.YOUR_VIEW.addSubview(placementView)
placementView.load()
}
}
```
## Handle Login : via AutoLogin Approach
To Auto Login in the SDK, You need to call below method, whenever user is log in to your application.
**Note**: You don't need to call the below method if you have implemented the Embed With SSO already.
```swift ViewController.swift theme={null}
GenuinSDK.shared.ssoLogin(ssoToken: "YOUR_SSO_TOKEN")
```
**Handle AutoLogin in Embed**
```swift with embed theme={null}
GenuinSDK.shared.initializeEmbed(embedId: "EMBED_ID", uniqueId: "YOUR_UNIQUE_ID", containerView: YOUR_VIEW, viewConroller: YOUR_VIEW_CONTROLLER, ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME", "mobile" :"MOBILE_NO"], contextualParams: ["page_context": "CONTEXT_TEXT", "geo": { "lat": LATITUDE_VALUE, "long": LONGITUDE_VALUE }], embedConfiguration: embedConfiguration)
```
```swift withtout embed theme={null}
GenuinSDK.shared.ssoLogin(ssoToken: "YOUR_SSO_TOKEN", params: ["name" :"FULL_NAME", "nickname" : "USER_NAME"])
```
```swift with completion handler theme={null}
GenuinSDK.shared.ssoLogin(ssoToken: "YOUR_SSO_TOKEN") { status in
}
// Where status of login = true or false
```
## Custom Login
If you want to handle login process as per your requirement then follow the below steps:
**Step 1**: Assign Delegate while initializing Genuin SDK
```swift Swift theme={null}
GenuinSDK.shared.delegate = self ( YOUR_ANY_CLASS )
```
**Step 2**: Extend GenuinDelegate & Present your own controller on provided base controller
```swift Swift theme={null}
extension YOUR_ANY_CLASS : GenuinDelegate{
func presentLoginViewController(baseViewController : UIViewController) {
guard let loginVC = GET AND ASSIGN YOUR CONTROLLER
baseViewController.present(loginVC, animated: true)
}
}
```
**Step 3**: Must call below login service from Genuin, to keep user logged in, in Genuin SDK.
```swift Swift theme={null}
GenuinSDK.shared.ssoLogin(ssoToken: "YOUR_SSO_TOKEN", params: ["name" : "FULL_NAME", "nickname" : "USER_NAME"])
```
## Handle Logout : via AutoLogin Approach
Whenever user logs out from your application call the below method.
```swift ViewController.swift theme={null}
GenuinSDK.shared.ssoLogout()
```
```swift with completion handler theme={null}
GenuinSDK.shared.ssoLogout { status in
}
// Where status of logout = true or false
```
## Handling Deep Link
**Note**: Make sure you have followed the installation steps in order to handle the deep links.
**Prerequisite**:
1. Make sure you have white labelled your community by following these [steps](https://resources.begenuin.com/retail-media/build/how_to_white-label_your_community)
2. Enable Associated Domains in Certificates, Identifiers & Profiles using your Apple Developer account at [https://developer.apple.com/account/resources/identifiers/list](https://developer.apple.com/account/resources/identifiers/list)
3. Create apple-app-site-association (without extension) file with following settings:
```json apple-app-site-association theme={null}
{"appclips":{"apps":["YOUR_TEAM_ID.APP_BUNDLE_ID.Clip"]},"applinks":{"apps":[],"details":[{"paths":["/*"],"appID":"YOUR_TEAM_ID.APP_BUNDLE_ID"}]}}
```
Once the file is created, host it on the white labeled domain at `https://YOUR_WHITE-LABELLED_DOMAIN/.well-known/apple-app-site-association`
4. Add Associated Domains in capabilities if not already,
Add applinks in domains, for Example:
applinks: `YOUR_WHITE-LABELLED_DOMAIN`
applinks: `www.YOUR_WHITE-LABELLED_DOMAIN`
To handle deep links in your app use the following methods.
```swift SceneDelegate.swift theme={null}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
handleGenuinDeeplink(deeplinkURL: connectionOptions.userActivities.first?.webpageURL)
}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
//redirect if genuin SDK handles the deeplink
handleGenuinDeeplink(deeplinkURL: userActivity.webpageURL)
}
func handleGenuinDeeplink(deeplinkURL: URL?) {
if let dlURL = deeplinkURL, GenuinSDK.shared.willHandleDeepLink(url: dlURL){
if let rootVC = window?.rootViewController as? UIViewController{
DispatchQueue.main.async {
GenuinSDK.shared.handleDeeplink(viewController: rootVC)
}
}
}
}
}
```
```swift AppDelegate.swift theme={null}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
//redirect if genuin SDK handles the deeplink
if let dlURL = userActivity.webpageURL , GenuinSDK.shared.willHandleDeepLink(url: dlURL){
if let rootVC = window?.rootViewController as? UIViewController {
GenuinSDK.shared.handleDeeplink(viewController: rootVC)
}
}
return true
}
```
**Note**: `GenuinSDK.shared.willHandleDeepLink(url: dlURL)` function will check whether `GenuinSDK` will handle the given deeplink or not. You can use it according to your deeplink redirection flow.
### Instructions for `SceneDelegate`:
Handle deep links using the root view controller by calling `GenuinSDK.shared.handleDeeplink(viewController: rootVC)`.
### Instructions for `AppDelegate`:
Use `GenuinSDK.shared.handleDeeplink(viewController: rootVC)` to manage the deep link using the app's root view controller.
**Note**:
1. To handle the Deeplink from another controller call the `GenuinSDK.shared.handleDeeplink(viewController: vc)` function from specific controller
2. If you are following the `SceneDelegate` method then calling this `GenuinSDK.shared.handleDeeplink(viewController: self)` function is mandatory
```swift theme={null}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
GenuinSDK.shared.handleDeeplink(viewController: self)
}
```
### Optional LinkOutInterceptor
If you want to intercept Linkout clicks, you can implement `GenuinLinkOutInterceptorDelegate` as below:
Step 1: Assign Delegate `GenuinLinkOutInterceptorDelegate`:
```swift YourClass.swift theme={null}
GenuinSDK.shared.registerLinkoutInterceptor(associateDomains: [ARRAY_OF_ASSOCIATED_DOMAINS_HANDLED_BY_YOUR_APP], linkOutInterceptorDelegate: YOUR_ANY_CLASS)
```
**Note**:
`ARRAY_OF_ASSOCIATED_DOMAINS_HANDLED_BY_YOUR_APP` accepts associcated domains supported by your apps. You can pass comma seperated domains like e.g. \["apple.com", "[https://apple.com](https://apple.com)", "[www.apple.com](http://www.apple.com)", "applinks:apple.com"]
`YOUR_ANY_CLASS` can be class which you want to handle the delegate method in.
Step 2: Handle callback method
```swift YourClass.swift theme={null}
extension YOUR_ANY_CLASS : GenuinLinkOutInterceptorDelegate{
func onLinkOutIntercept(urlString: String, viewController: UIViewController?) {
/*
This callback will be triggered when user clicks on linkouts from any video and if it's domain matches the associateDomains provided.
You will receive the url clicked and a current controller so you can handle the deeplink redirection from here in your app
*/
}
}
```
## Handling Push Notifications
### Using Firebase
1. Create an app in your firebase console by following [these steps](https://firebase.google.com/docs/cloud-messaging/ios/client)
2. Download the `GoogleService-Info.plist` file and add it in xcode project
3. Add pod in pod file
```swift podfile theme={null}
pod 'FirebaseMessaging', '~> 10.24.0'
```
4. To enable the push notifications functionality then enable the Push Notifications in your target. To do so, `Select the target > Signing & Capabilities > Add Capability of Push Notification`
5. Import
```swift Swift theme={null}
import FirebaseMessaging
import GenuinCore
```
AppDelegate
```swift AppDelegate.swift theme={null}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
//Assign APNS token and notify sdk
Messaging.messaging().apnsToken = deviceToken
GenuinSDK.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken, isFCMIntegrated: true)
}
```
**Note**: Pass `true` value in `isFCMIntegrated` parameter, as we are using the Firebase.
6. Initialize
SceneDelegate
```swift SceneDelegate.swift theme={null}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
//Register the notification
registerForNotification()
//configure firebase
FirebaseApp.configure()
//set delegate , extend current class with MessagingDelegate
Messaging.messaging().delegate = self
}
```
7. Place this code to take the user permission for Push Notification
```swift SceneDelegate.swift theme={null}
func registerForNotification(){
//Take permission and register remote notification
let current = UNUserNotificationCenter.current()
current.getNotificationSettings(completionHandler: { (settings) in
if settings.authorizationStatus == .notDetermined{
self.requestForNotificationPermission()
}else if settings.authorizationStatus == .authorized {
UNUserNotificationCenter.current().delegate = self
DispatchQueue.main.async{
UIApplication.shared.registerForRemoteNotifications()
}
}
})
}
private func requestForNotificationPermission(){
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in
print(granted)
}
UIApplication.shared.registerForRemoteNotifications()
}
```
8. Extend `MessagingDelegate` and Add follwing method:
```swift SceneDelegate.swift theme={null}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
if let token = fcmToken {
//fetch and register token
getInstanceID()
}
}
func getInstanceID(){
Messaging.messaging().token { token, error in
// Check for error. Otherwise do what you will with token here
if let error = error {
print("Error fetching remote instance ID: \(error)")
} else if let result = token {
print("Remote instance ID token: \(result)")
GenuinSDK.shared.registerFCMToken(token: result)
}
}
}
```
9. To Handle the Push Notification Redirection whenever the user taps, follow the below code
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if let userInfo = response.notification.request.content.userInfo as? [String: AnyObject]{
//notify firebase
Messaging.messaging().appDidReceiveMessage(userInfo)
//check if genuin will handle notification
if GenuinSDK.shared.willHandleNotification(userInfo: userInfo){
//notify to redirect
GenuinSDK.shared.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler)
//notification notification
if let rootVC = window?.rootViewController as? UIViewController{
GenuinSDK.shared.handleNotifications(viewController: rootVC)
}
}
}
}
```
**Note**: `GenuinSDK.shared.willHandleNotification(userInfo: userInfo)` function will check whether `GenuinSDK` will handle the given notification or not. You can use it according to your notification redirection flow.
10. To configure notification UI
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
print("\(userInfo)")
//mention design type for notification
completionHandler([.list, .badge, .sound])
}
```
11. If you want to handle the notification when app is opened then follow the below code
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
GenuinSDK.shared.userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler)
if let rootVC = window?.rootViewController as? UIViewController{
GenuinSDK.shared.handleNotifications(viewController: rootVC)
}
//mention design type for notification
completionHandler([.list, .badge, .sound])
}
```
**Note**: To handle the notification from another controller call the `GenuinSDK.shared.handleNotifications(viewController: YOUR_VIEW_CONTROLLER)` function
### Using APNS
1. To enable the push notifications functionality then enable the Push Notifications in your target. To do so, `Select the target > Signing & Capabilities > Add Capability of Push Notification`
2. Import
```swift Swift theme={null}
import GenuinCore
```
AppDelegate
```swift AppDelegate.swift theme={null}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
//Assign APNS token and notify sdk
GenuinSDK.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken, isFCMIntegrated: false)
}
```
**Note**: Pass `false` value in `isFCMIntegrated` parameter, as we are not using the Firebase.
SceneDelegate
Initialize
```swift SceneDelegate.swift theme={null}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
//Register the notification
registerForNotification()
}
```
3. Place this code to take the user permission for Push Notification
```swift SceneDelegate.swift theme={null}
func registerForNotification(){
//Take permission and register remote notification
let current = UNUserNotificationCenter.current()
current.getNotificationSettings(completionHandler: { (settings) in
if settings.authorizationStatus == .notDetermined{
self.requestForNotificationPermission()
}else if settings.authorizationStatus == .authorized {
UNUserNotificationCenter.current().delegate = self
DispatchQueue.main.async{
UIApplication.shared.registerForRemoteNotifications()
}
}
})
}
private func requestForNotificationPermission(){
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in
print(granted)
}
UIApplication.shared.registerForRemoteNotifications()
}
```
4. To Handle the Push Notification Redirection whenever the user taps, follow the below code
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if let userInfo = response.notification.request.content.userInfo as? [String: AnyObject]{
//check if genuin will handle notification
if GenuinSDK.shared.willHandleNotification(userInfo: userInfo){
//notify to redirect
GenuinSDK.shared.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler)
//notification notification
if let rootVC = window?.rootViewController as? UIViewController{
GenuinSDK.shared.handleNotifications(viewController: rootVC)
}
}
}
}
```
**Note**: `GenuinSDK.shared.willHandleNotification(userInfo: userInfo)` function will check whether `GenuinSDK` will handle the given notification or not. You can use it according to your notification redirection flow.
5. To configure notification UI
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
print("\(userInfo)")
//mention design type for notification
completionHandler([.list, .badge, .sound])
}
```
6. If you want to handle the notification when app is opened then follow the below code
```swift SceneDelegate.swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void){
let userInfo = notification.request.content.userInfo
GenuinSDK.shared.userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler)
if let rootVC = window?.rootViewController as? UIViewController{
GenuinSDK.shared.handleNotifications(viewController: rootVC)
}
//mention design type for notification
completionHandler([.list, .badge, .sound])
}
```
**Note**: To handle the notification from another controller call the `GenuinSDK.shared.handleNotifications(viewController: YOUR_VIEW_CONTROLLER)` function.
## What’s next?
Integrate Android SDK in Your ecosystem.
Integrate Web SDK in your ecosystem.
Integrate React Native SDK in your ecosystem.
## Support
If you need any assistance or have any questions, feel free to email us at [support@begenuin.com](mailto:support@begenuin.com).
# React Native SDK
Source: https://resources.begenuin.com/developers/sdk-docs/react_native_sdk
The genuin-react-native SDK is designed to seamlessly integrate the features of the "Genuin" mobile application into your own React Native projects. Follow the instructions below to install and integrate the SDK into your application.
# Installation
Run the below code to install the react native
```
npm install genuin-react-native
```
# Android
To install the React Native in Android perform the below steps:
### Android Configuration
**Step 1**: In `android/app/build.gradle`:
```kotlin build.gradle theme={null}
android {
defaultConfig {
minSdk = 24
}
}
```
**Step 2**: In `android/app/src/main/AndroidManifest.xml`:
```kotlin AndroidManifest.xml theme={null}
```
**Step 3**: Change theme in `android/app/src/main/res/values/styles.xml`:
Our SDK is using Material components so in order to use our sdk you need to use material theme as shown in below example
```kotlin styles.xml theme={null}
```
**Step 4**: Create `android/app/proguard-rules.pro`, add the following lines:
```kotlin proguard-rules.pro theme={null}
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
-dontwarn com.facebook.imagepipeline.nativecode.WebpTranscoder
-keep class com.bumptech.glide.**{*;}
-keep public class * {
public *;
protected *;
}
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@retrofit2.http.* ;
}
# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit
# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn java.lang.reflect.AnnotatedType
-dontwarn com.google.api.client.http.GenericUrl
-dontwarn com.google.api.client.http.HttpHeaders
-dontwarn com.google.api.client.http.HttpRequest
-dontwarn com.google.api.client.http.HttpRequestFactory
-dontwarn com.google.api.client.http.HttpResponse
-dontwarn com.google.api.client.http.HttpTransport
-dontwarn com.google.api.client.http.javanet.NetHttpTransport$Builder
-dontwarn com.google.api.client.http.javanet.NetHttpTransport
-dontwarn com.squareup.picasso.Picasso
-dontwarn com.squareup.picasso.RequestCreator
-dontwarn java.awt.image.BufferedImage
-dontwarn javax.imageio.ImageIO
-dontwarn org.joda.time.Instant
-dontwarn org.junit.Assert
-dontwarn org.slf4j.impl.StaticLoggerBinder
-dontwarn org.slf4j.impl.StaticMDCBinder
-dontwarn org.slf4j.impl.StaticMarkerBinder
# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* ; }
-keep,allowobfuscation interface <1>
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.begenuin.begenuin.data.model.** { ; }
-keep class com.begenuin.begenuin.vo.** { ; }
# RenderScript
-keepclasseswithmembernames class * {
native ;
}
-keep class androidx.renderscript.** { *; }
-keepattributes *Annotation*
-keep class com.giphy.sdk.core.models.** { *; }
-keep class com.giphy.sdk.ui.views.** { *; }
-keep public class * implements java.lang.reflect.Type
-keep class com.google.mediapipe.solutioncore.** {*;}
-keep class com.google.protobuf.** {*;}
-dontwarn com.begenuin.sdk.BR
-dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManager
-dontwarn com.google.android.play.core.splitinstall.SplitInstallManagerFactory
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest$Builder
-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest
-dontwarn com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
-dontwarn com.google.android.play.core.tasks.OnFailureListener
-dontwarn com.google.android.play.core.tasks.OnSuccessListener
-dontwarn com.google.android.play.core.tasks.Task
-dontwarn com.google.mediapipe.proto.CalculatorProfileProto$CalculatorProfile
-dontwarn com.google.mediapipe.proto.GraphTemplateProto$CalculatorGraphTemplate
-dontwarn javax.lang.model.AnnotatedConstruct
-dontwarn javax.lang.model.SourceVersion
-dontwarn javax.lang.model.element.AnnotationMirror
-dontwarn javax.lang.model.element.AnnotationValue
-dontwarn javax.lang.model.element.AnnotationValueVisitor
-dontwarn javax.lang.model.element.Element
-dontwarn javax.lang.model.element.ElementKind
-dontwarn javax.lang.model.element.ElementVisitor
-dontwarn javax.lang.model.element.ExecutableElement
-dontwarn javax.lang.model.element.Name
-dontwarn javax.lang.model.element.NestingKind
-dontwarn javax.lang.model.element.PackageElement
-dontwarn javax.lang.model.element.QualifiedNameable
-dontwarn javax.lang.model.element.TypeElement
-dontwarn javax.lang.model.element.TypeParameterElement
-dontwarn javax.lang.model.element.VariableElement
-dontwarn javax.lang.model.type.ArrayType
-dontwarn javax.lang.model.type.DeclaredType
-dontwarn javax.lang.model.type.ErrorType
-dontwarn javax.lang.model.type.ExecutableType
-dontwarn javax.lang.model.type.IntersectionType
-dontwarn javax.lang.model.type.NoType
-dontwarn javax.lang.model.type.NullType
-dontwarn javax.lang.model.type.PrimitiveType
-dontwarn javax.lang.model.type.TypeKind
-dontwarn javax.lang.model.type.TypeMirror
-dontwarn javax.lang.model.type.TypeVariable
-dontwarn javax.lang.model.type.TypeVisitor
-dontwarn javax.lang.model.type.WildcardType
-dontwarn javax.lang.model.util.AbstractElementVisitor8
-dontwarn javax.lang.model.util.ElementFilter
-dontwarn javax.lang.model.util.Elements
-dontwarn javax.lang.model.util.SimpleAnnotationValueVisitor8
-dontwarn javax.lang.model.util.SimpleElementVisitor8
-dontwarn javax.lang.model.util.SimpleTypeVisitor8
-dontwarn javax.lang.model.util.Types
-dontwarn javax.tools.Diagnostic$Kind
-dontwarn javax.tools.JavaFileObject$Kind
-dontwarn javax.tools.JavaFileObject
-dontwarn javax.tools.SimpleJavaFileObject
```
Want to override our default loader?
We are using `lottie` animation for our loader. You can put your custom lottie animation loader with the name `loader_mix.json` in the `android/app/src/main/res/raw` folder. Make sure you use the same name as provided.
### Quick Start
**1. Initialize SDK**
```kotlin theme={null}
import android.content.Intent
import android.os.Bundle
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
import com.genuinsdk.GenuinSDKPluginModule
class MainActivity : ReactActivity() {
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
override fun getMainComponentName(): String = "YourApp"
/**
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
*/
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GenuinSDKPluginModule.initSDK(application, "YOUR_API_KEY")
}
}
```
**2. Handling Deeplink**
To handle deep link place the below code in `android/app/src/main/AndroidManifest.xml` file:
```kotlin AndroidManifest.xml theme={null}
```
```kotlin theme={null}
import android.content.Intent
import android.os.Bundle
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
import com.genuinsdk.GenuinSDKPluginModule
class MainActivity : ReactActivity() {
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
override fun getMainComponentName(): String = "YourApp"
/**
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
*/
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GenuinSDKPluginModule.initSDK(application, "YOUR_API_KEY")
if (intent != null && intent.data != null) {
handleDeepLink(intent)
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleDeepLink(intent)
}
private fun handleDeepLink(intent: Intent?) {
intent?.data?.let {
GenuinSDKPluginModule.handleDeepLink(this@MainActivity, intent)
}
}
}
```
**3. Handling Push Notifications**
To handle the push notification place the below code In `android/app/build.gradle` file:
```kotlin build.gradle theme={null}
buildscript {
dependencies {
classpath("com.google.gms:google-services:4.4.2")
}
}
```
# iOS
### iOS Configuration
**1. In ios/Podfile**
```swift ios/Podfile theme={null}
ENV['USE_FRAMEWORKS'] = 'dynamic'
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
platform :ios, min_ios_version_supported
prepare_react_native_project!
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
end
target 'YourApp' do
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
pre_install do |installer|
installer.pod_targets.each do |pod|
if pod.name.eql?('RNReanimated')
def pod.build_type
Pod::BuildType.static_library
end
end
end
end
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
# :ccache_enabled => true
)
installer.pods_project.targets.each do |target|
if target.name == 'Giphy'
`xcrun -sdk iphoneos bitcode_strip -r Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK -o Pods/Giphy/GiphySDK/GiphyUISDK.xcframework/ios-arm64_armv7/GiphyUISDK.framework/GiphyUISDK`
end
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.1'
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
end
```
### Quick Start
**1. Initialize SDK**
```swift theme={null}
import UIKit
import React
import React_RCTAppDelegate
import ReactAppDependencyProvider
import Firebase
@main
class AppDelegate: RCTAppDelegate, UNUserNotificationCenterDelegate {
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
self.moduleName = "YourApp"
self.dependencyProvider = RCTAppDependencyProvider()
if FirebaseApp.app() == nil {
FirebaseApp.configure()
}
UNUserNotificationCenter.current().delegate = self
UIApplication.shared.registerForRemoteNotifications()
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = [:]
GenuinModuleObjCWrapper.initSDK("YOUR_API_KEY", loaderName: "YOUR_LOTTIE_LOADER_NAME", showNavigationBar: nil)
addNavVC()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
func addNavVC(){
DispatchQueue.main.async {
if let rootVC = self.window.rootViewController {
self.window.rootViewController = nil
let navVC = GenuinModuleObjCWrapper.getGenuinNavigationController(rootVC)
navVC?.setNavigationBarHidden(true, animated: true);
self.window.rootViewController = navVC
self.window.makeKeyAndVisible()
}
}
}
override func sourceURL(for bridge: RCTBridge) -> URL? {
self.bundleURL()
}
override func bundleURL() -> URL? {
#if DEBUG
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
#else
Bundle.main.url(forResource: "main", withExtension: "jsbundle")
#endif
}
}
```
If your project has AppDelegate.swift file create the following wrapper classes in Objective-C in order to communicate with genuin's react-native module,
1. `GenuinModuleObjCWrapper.h`
```swift theme={null}
#import
#import
NS_ASSUME_NONNULL_BEGIN
@interface GenuinModuleObjCWrapper : NSObject
+ (void)initSDK:(NSString *_Nullable)apiKey loaderName:(NSString *_Nullable)loaderName showNavigationBar:(BOOL *_Nullable)showNavigationBar;
+ (BOOL)application:(UIApplication *_Nullable)application continueUserActivity:(NSUserActivity *_Nullable)userActivity restorationHandler:(void (^_Nullable)(NSArray> * _Nullable))restorationHandler;
+ (BOOL)handleDeepLink:(NSURL * _Nullable)dlURL controller:(UIViewController * _Nullable)controller;
+ (void)handleForegroundNotification:(NSDictionary *)notificationData;
+ (UINavigationController*_Nullable)getGenuinNavigationController:(UIViewController*)viewController;
@end
NS_ASSUME_NONNULL_END
```
2. `GenuinModuleObjCWrapper.mm`
```swift theme={null}
#import "GenuinModuleObjCWrapper.h"
#import "GenuinSDKPlugin.h"
@implementation GenuinModuleObjCWrapper
+ (void)initSDK:(NSString *_Nullable)apiKey loaderName:(NSString *_Nullable)loaderName showNavigationBar:(BOOL *_Nullable)showNavigationBar {
[GenuinSDKPlugin initSDK:apiKey loaderName:loaderName showNavigationBar:showNavigationBar];
}
+ (BOOL)application:(UIApplication *_Nullable)application continueUserActivity:(NSUserActivity *_Nullable)userActivity restorationHandler:(void (^_Nullable)(NSArray> * _Nullable))restorationHandler {
return [GenuinSDKPlugin application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}
+ (BOOL)handleDeepLink:(NSURL * _Nullable)dlURL controller:(UIViewController * _Nullable)controller {
return [GenuinSDKPlugin handleDeepLink:dlURL controller:controller];
}
+ (void)handleForegroundNotification:(NSDictionary *)notificationData {
[GenuinSDKPlugin handleForegroundNotification:notificationData];
}
+ (UINavigationController*_Nullable)getGenuinNavigationController:(UIViewController*)viewController {
return [GenuinSDKPlugin getGenuinNavigationController: viewController];
}
@end
```
3. `YourApp-Bridging-Header.h`
```swift theme={null}
#import "GenuinModuleObjCWrapper.h"
```
**2. Handling Deep Link**
To handle deeplink place the below in `AppDelegate.swift` file:
Prerequisite step : [Link](https://resources.begenuin.com/developers/sdk-docs/ios_sdk#handling-deep-link)
In `AppDelegate.swift`:
```swift AppDelegate.swift theme={null}
import UIKit
import React
import React_RCTAppDelegate
import ReactAppDependencyProvider
import Firebase
@main
class AppDelegate: RCTAppDelegate, UNUserNotificationCenterDelegate {
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
let result = GenuinModuleObjCWrapper.application(application, continue: userActivity, restorationHandler: restorationHandler)
if GenuinModuleObjCWrapper.handleDeepLink(userActivity.webpageURL, controller: window.rootViewController) {
return true
}
return result
}
}
```
**3. Handling Push Notification**
To handle the push notification place the below code In `AppDelegate.swift` file:
```swift AppDelegate.swift theme={null}
import UIKit
import React
import React_RCTAppDelegate
import ReactAppDependencyProvider
import Firebase
@main
class AppDelegate: RCTAppDelegate, UNUserNotificationCenterDelegate {
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
print("deviceToken", deviceToken)
}
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print("\(userInfo )")
completionHandler(.newData)
}
override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: any Error) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.list, .banner, .badge, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if response.notification.request.trigger == nil {
let notificationData = ["data": response.notification.request.content.userInfo]
GenuinModuleObjCWrapper.handleForegroundNotification(notificationData)
}
completionHandler()
}
}
```
# Web
### Web Configuration
To integrate the `genuin-react-native` SDK into your application, follow these steps:
1. Import the Feed Component: In your `app.jsx` file, import the `Feed` component from the `genuin-react-native` SDK.
2. Obtain Your API Key: Contact the Genuin team to obtain your unique `API_KEY`. This key is essential for authenticating your application with the Genuin service.
3. Implement the `Feed` Component: Use the Feed component within your application, passing the `API_KEY` as a prop. Below is an example of how to implement this:
```javascript javascript theme={null}
import React from "react";
import Feed from "genuin-react-native";
export default function App() {
return ;
}
```
**Carousel**
```javascript javascript theme={null}
import React from "react";
import Carousel from "genuin-react-native";
export default function App() {
return ;
}
```
**Example**
Here's a complete example of how your `app.jsx` file might look:
```javascript javascript theme={null}
import React from "react";
import { SafeAreaView, StyleSheet, Text } from "react-native";
import Feed from "genuin-react-native";
export default function App() {
return (
Welcome to the Genuin Feed
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF",
},
header: {
fontSize: 20,
textAlign: "center",
margin: 10,
},
});
```
**Additonal Information**
**Handling Errors**
Ensure you handle any potential errors gracefully. The Feed component can throw errors if the API key is invalid or if there are network issues. Implement error handling in your component as needed.
**Styling the Feed**
You can style the Feed component using standard React Native styling techniques. Customize it to fit the design and aesthetics of your application.
**Updating the API Key**
If you need to update your API key, simply modify the `apiKey` prop passed to the Feed component. Ensure your application is reloaded to apply the changes.
# React Native
**1. Load Carousel Embed View**
```
import React, { useRef } from 'react';
import { Carousel, PlayPauseRef } from 'genuin-react-native';
export default function App() {
const carouselRef = useRef(null);
return ;
}
```
**Note**: 1. You can set height and width of the Carousel as per your need.
2\. You can use `carouselRef.current?.pause()` and `carouselRef.current?.resume()` for pause and resume video play in Carousel.
To configure the EmbedParams based on your need you can pass the below values.
**embedId** = The Embed Id that you want to load.
**uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
**ssoToken** = This is an optional parameter. To auto login in the SDK, you shall pass “YOUR\_SSO\_TOKEN” in order to implement Embed with SSO in your app.
**interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
**isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter “interactionDeepLink” will be ignored. If not passed then the regular flow will work.
**Note**: For using isDirectDeepLinkEnabled parameter, you must have white labelled your domain first and also integrated the Handling deep link part in your main app in which you want to redirect this video to.
**isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
**2. Load Standard Wall Embed View**
```
import React, { useRef } from 'react';
import { PlayPauseRef, StandardWall } from 'genuin-react-native';
export default function App() {
const standardWallRef = useRef(null);
return ;
}
```
**Note**: 1. You can set height and width of the StandardWall as per your need.
2\. You can use `standardWallRef.current?.pause()` and `standardWallRef.current?.resume()` for pause and resume video play in StandardWall.
To configure the EmbedParams based on your need you can pass the below values.
**embedId** = The Embed Id that you want to load.
**uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
**ssoToken** = This is an optional parameter. To auto login in the SDK, you shall pass “YOUR\_SSO\_TOKEN” in order to implement Embed with SSO in your app.
**interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
**isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter “interactionDeepLink” will be ignored. If not passed then the regular flow will work.
**Note**: For using isDirectDeepLinkEnabled parameter, you must have white labelled your domain first and also integrated the Handling deep link part in your main app in which you want to redirect this video to.
**isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
**3. Load FullScreen Embed View**
```
import React, { useRef } from 'react';
import { Feed, PlayPauseRef } from 'genuin-react-native';
export default function App() {
const feedRef = useRef(null);
return ;
}
```
**Note**: 1. You can set height and width of the Feed as per your need.
2\. You can use `feedRef.current?.pause()` and `feedRef.current?.resume()` for pause and resume video play in Feed.
To configure the EmbedParams based on your need you can pass the below values.
**embedId** = The Embed Id that you want to load.
**uniqueId** = This is an optional parameter. This uniqueId is used when we need to display same embed in multiple/same screen. We need to provide uniqueId for the same embedId in multiple/same screen.
**ssoToken** = This is an optional parameter. To auto login in the SDK, you shall pass “YOUR\_SSO\_TOKEN” in order to implement Embed with SSO in your app.
**interactionDeepLink** = This is an optional parameter. You can pass a deeplink URL in this parameter. If a deeplink URL is given then all the interaction/clicks in the full screen view will redirect to the deeplink URL given. If not passed then the regular flow will work. It should be a correct URL else user will not be redirected.
**isDirectDeepLinkEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true then all the interaction/clicks in the full screen view will redirect to the specific video in white labelled app associated with video and also value of this parameter “interactionDeepLink” will be ignored. If not passed then the regular flow will work.
**Note**: For using isDirectDeepLinkEnabled parameter, you must have white labelled your domain first and also integrated the Handling deep link part in your main app in which you want to redirect this video to.
**isShowProfileEnabled** = This is an optional boolean parameter. Default value is false. If this parameter is true and also if user is logged in than Profile picture will be visible in full screen view (right side top corner). On clicking the profile picture user will see the account settings and logout options.
**4. Load HomeFeed View(Android Specific)**
```
import React, { useRef } from 'react';
import { HomeFeed, PlayPauseRef } from 'genuin-react-native';
export default function App() {
const homeFeedRef = useRef(null);
return ;
}
```
**Note**: 1. You can set height and width of the HomeFeed as per your need.
2\. You can use `homeFeedRef.current?.pause()` and `homeFeedRef.current?.resume()` for pause and resume video play in HomeFeed.
**5. Handling Push Notifications**
**Prerequisite:**
Create firebase project and integrate into your app by following [https://firebase.google.com/docs/flutter/setup](https://firebase.google.com/docs/flutter/setup)
Step1: Create `firebase_options.dart` in lib folder and add below details in that file.
```
import 'package:firebase_core/firebase_core.dart';
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (Platform.isAndroid) {
return const FirebaseOptions(
apiKey: 'YOUR-ANDROID-API-KEY',
appId: 'YOUR-ANDROID-APP-ID',
messagingSenderId: 'YOUR-SENDER-ID',
projectId: 'YOUR-PROJECT-ID',
storageBucket: 'YOUR-STORAGE-BUCKET',
);
}else{
return const FirebaseOptions(
apiKey: 'YOUR-IOS-API-KEY',
appId: 'YOUR-IOS-APP-ID',
messagingSenderId: 'YOUR-SENDER-ID',
projectId: 'YOUR-PROJECT-ID',
storageBucket: 'YOUR-STORAGE-BUCKET',
);
}
}
}
```
Step 2: Handling background/foreground notifications
**Note**: Here for Android you need to provide small notification icon as "icon" key for foreground notifications. This icon needs to be in your flutter as well as android folder.
```
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:genuin_sdk/genuin_sdk.dart';
import 'firebase_options.dart';
// This method will be called when app is in background and push received
Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
}
final _genuinSdkPlugin = GenuinSdk();
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
name: 'YOUR_FIREBASE_PROJECT_NAME',
options: DefaultFirebaseOptions.currentPlatform,
);
final messaging = FirebaseMessaging.instance;
// Asking push notification permission
final settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
// If permission is granted than get firebase token and register it with Genuin SDK
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
String? token = await messaging.getToken();
if (token != null) {
await _genuinSdkPlugin.registerFCMToken(token);
}
}
// Check for initial notification that opened the app
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) {
// Handle navigation or actions
final notificationData = {
'title': initialMessage.notification?.title,
'body': initialMessage.notification?.body,
'data': initialMessage.data,
};
var willHandleNotification = await _genuinSdkPlugin
.willHandleBackgroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleBackgroundNotifications(notificationData);
} else {
// Your notification handling
}
}
// This method will be called when app is in foreground and push received
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
if (kDebugMode) {
print('Handling a foreground message: ${message.messageId}');
print('Message data: ${message.data}');
print('Message notification: ${message.notification?.title}');
print('Message notification: ${message.notification?.body}');
}
final notificationData = {
'title': message.notification?.title,
'body': message.notification?.body,
'data': message.data,
'icon': 'mipmap/ic_notification'
// OR 'icon':'drawable/ic_notification'[if image put under drawable folder]
};
var willHandleNotification = await _genuinSdkPlugin
.willHandleForegroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleForegroundNotifications(notificationData);
} else {
// Your notification handling
}
});
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
//This method will be called when user clicked on notification[Push notification is received when app is in background/killed]
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
final notificationData = {
'title': message.notification?.title,
'body': message.notification?.body,
'data': message.data,
};
var willHandleNotification = await _genuinSdkPlugin
.willHandleBackgroundNotifications(notificationData);
if (willHandleNotification == true) {
_genuinSdkPlugin.handleBackgroundNotifications(notificationData);
} else {
// Your notification handling
}
});
runApp(const MyApp());
}
```
**5. Handle SSO Login Explicitly in SDK**
To Auto Login in the SDK, You need to call below method, whenever user is log in to your application.
**Note**: You don’t need to call the below method if you have implemented the Embed With SSO already.
```
import 'package:genuin_sdk/genuin_sdk.dart';
final _genuinSdkPlugin = GenuinSdk();
await _genuinSdkPlugin.ssoLogin("YOUR_SSO_TOKEN");
```
**6. Handle SSO Logout in SDK**
```
import 'package:genuin_sdk/genuin_sdk.dart';
final _genuinSdkPlugin = GenuinSdk();
await _genuinSdkPlugin.ssoLogout();
```
## Support
For further assistance with integrating the `genuin-react-native` SDK, please contact the Genuin support team or refer to the official documentation. The Genuin team is available to help you with any issues or questions you might have during the integration process.
# Web SDK
Source: https://resources.begenuin.com/developers/sdk-docs/web_sdk
Genuin Web SDK comprises features such as brand feed, communities, and groups.
# Prerequisites
Genuin will provide you with the established community under the subdomain URL - website.begenuin.com which you can manage under your brand control center login.
## Steps to embed Brand Community:
To embed your Brand community into your website, follow the steps below:
1. Identify the location on your website where you want to embed the community widget.
2. Paste the provided code block into the desired location in your website's HTML markup.
3. Adjust the height and width of the embed container as per your design requirements.
You can specify these dimensions within the code block itself.
## Implementation
### HTML Structure
#### Single Embeds (html)
```html Embed_Without_AutoLogin theme={null}
```
```html Embed_With_AutoLogin theme={null}
```
#### Embed With Multi Embeds (html)
##### Prerequisites
Before implementing the multi-embed setup, ensure you have:
1. Valid Genuin API credentials
2. Unique embed IDs for each widget instance
3. Access to the Genuin SDK
The multi-embed approach requires separate containers for each widget instance. Each container
must have unique identifiers and proper data attributes.
**Note:**
1. Ensure each container has a unique `id` attribute
2. The multi-embed approach also works for single embeds, so you can use it for both cases if you prefer a unified setup.
```html Embed_With_Multi_Embeds theme={null}
```
#### Embed With Contextual Feed (html)
Only include the parameters necessary to retrieve a contextual feed.
```html Embed_With_Multiple_Embeds theme={null}
```
```html Embed_With_Single_Embeds theme={null}
```
### Angular Structure
**Note** : If you prefer not to inject the script dynamically using JavaScript, you can also include it directly in your HTML using a script tag.
However, before initializing or interacting with the embedded element, ensure the
following:
1. The script has finished loading successfully.
2. The target DOM element is present on the page.
#### Single Embeds (Angular)
The following code snippet has been developed using Angular version 16.
```typescript Embed_Without_AutoLogin theme={null}
// src/app/genuin-sdk.component.ts
import {
Component,
AfterViewInit,
OnDestroy,
ViewEncapsulation,
} from "@angular/core";
@Component({
selector: "genuin-sdk",
standalone: true,
template: `
`,
encapsulation: ViewEncapsulation.None,
})
export class GenuinSdkComponent implements AfterViewInit, OnDestroy {
private scriptElement: HTMLScriptElement | null = null;
private genuinInitialized = false;
ngAfterViewInit() {
(window as any).onGenuinReady = (genuin: any) => {
if (!this.genuinInitialized) {
genuin.initialize({
embed_id: "Your Embed ID",
api_key: "Your API Key",
});
this.genuinInitialized = true;
}
};
this.scriptElement = document.createElement("script");
this.scriptElement.src = "https://media.begenuin.com/sdk/gen_sdk.min.js";
this.scriptElement.async = true;
document.body.appendChild(this.scriptElement);
}
ngOnDestroy() {
if (this.scriptElement) {
document.body.removeChild(this.scriptElement);
}
delete (window as any).onGenuinReady;
}
}
// src/app/app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
import { GenuinSdkComponent } from "./genuin-sdk.component";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, GenuinSdkComponent],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
```
```typescript Embed_With_AutoLogin theme={null}
// src/app/genuin-sdk.component.ts
import {
Component,
AfterViewInit,
OnDestroy,
ViewEncapsulation,
} from "@angular/core";
@Component({
selector: "genuin-sdk",
standalone: true,
template: `
`,
encapsulation: ViewEncapsulation.None,
})
export class GenuinSdkComponent implements AfterViewInit, OnDestroy {
private scriptElement: HTMLScriptElement | null = null;
private genuinInitialized = false;
ngAfterViewInit() {
(window as any).onGenuinReady = (genuin: any) => {
if (!this.genuinInitialized) {
genuin.initialize({
embed_id: "Your Embed ID",
api_key: "Your API Key",
token: "Your Authentication Token",
params: {
name: "Name",
mobile: "Contact Number",
email: "Email ID",
nickname: "Nickname",
profileImage: "Profile Image URL",
},
// Pass the token only if you want to enable autologin functionality.
// The token value can be a unique identifier (such as a session token) or an email address, depending on your authentication flow.
// To bypass autologin, provide the token along with any additional required parameters.
// Include only the parameters necessary for your use case.
});
this.genuinInitialized = true;
}
};
this.scriptElement = document.createElement("script");
this.scriptElement.src = "https://media.begenuin.com/sdk/gen_sdk.min.js";
this.scriptElement.async = true;
document.body.appendChild(this.scriptElement);
}
ngOnDestroy() {
if (this.scriptElement) {
document.body.removeChild(this.scriptElement);
}
delete (window as any).onGenuinReady;
}
}
// src/app/app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
import { GenuinSdkComponent } from "./genuin-sdk.component";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, GenuinSdkComponent],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
```
#### Embed With Multi Embeds (Angular)
##### Prerequisites
Before implementing the multi-embed setup, ensure you have:
1. Valid Genuin API credentials
2. Unique embed IDs for each widget instance
3. Access to the Genuin SDK
The multi-embed approach requires separate containers for each widget instance. Each container
must have unique identifiers and proper data attributes.
**Note:**
1. Ensure each container has a unique `id` attribute
2. The multi-embed approach also works for single embeds, so you can use it for both cases if you prefer a unified setup.
```typescript Embed_With_Multi_Embeds theme={null}
// src/app/genuin-sdk.component.ts
import {
Component,
AfterViewInit,
OnDestroy,
ViewEncapsulation,
} from "@angular/core";
@Component({
selector: "genuin-sdk",
standalone: true,
template: `
`,
encapsulation: ViewEncapsulation.None,
})
export class GenuinSdkComponent implements AfterViewInit, OnDestroy {
private scriptElement: HTMLScriptElement | null = null;
private genuinInitialized = false;
ngAfterViewInit() {
(window as any).onGenuinReady = (genuin: any) => {
if (!this.genuinInitialized) {
genuin.initialize({});
this.genuinInitialized = true;
}
};
this.scriptElement = document.createElement("script");
this.scriptElement.src = "https://media.begenuin.com/sdk/gen_sdk.min.js";
this.scriptElement.async = true;
document.body.appendChild(this.scriptElement);
}
ngOnDestroy() {
if (this.scriptElement) {
document.body.removeChild(this.scriptElement);
}
delete (window as any).onGenuinReady;
}
}
// src/app/app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
import { GenuinSdkComponent } from "./genuin-sdk.component";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, GenuinSdkComponent],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
```
#### Embed With Contextual Feed (Angular)
Only include the parameters necessary to retrieve a contextual feed.
```typescript Contextual_Feed theme={null}
// src/app/genuin-sdk.component.ts
import {
Component,
AfterViewInit,
OnDestroy,
ViewEncapsulation,
} from "@angular/core";
@Component({
selector: "genuin-sdk",
standalone: true,
template: `
`,
encapsulation: ViewEncapsulation.None,
})
export class GenuinSdkComponent implements AfterViewInit, OnDestroy {
private scriptElement: HTMLScriptElement | null = null;
private genuinInitialized = false;
ngAfterViewInit() {
(window as any).onGenuinReady = (genuin: any) => {
if (!this.genuinInitialized) {
genuin.initialize({});
this.genuinInitialized = true;
}
};
this.scriptElement = document.createElement("script");
this.scriptElement.src = "https://media.begenuin.com/sdk/gen_sdk.min.js";
this.scriptElement.async = true;
document.body.appendChild(this.scriptElement);
}
ngOnDestroy() {
if (this.scriptElement) {
document.body.removeChild(this.scriptElement);
}
delete (window as any).onGenuinReady;
}
}
// src/app/app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
import { GenuinSdkComponent } from "./genuin-sdk.component";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, GenuinSdkComponent],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
```
```typescript Single_Embeds theme={null}
// src/app/genuin-sdk.component.ts
import {
Component,
AfterViewInit,
OnDestroy,
ViewEncapsulation,
} from "@angular/core";
@Component({
selector: "genuin-sdk",
standalone: true,
template: `
`,
encapsulation: ViewEncapsulation.None,
})
export class GenuinSdkComponent implements AfterViewInit, OnDestroy {
private scriptElement: HTMLScriptElement | null = null;
private genuinInitialized = false;
ngAfterViewInit() {
(window as any).onGenuinReady = (genuin: any) => {
if (!this.genuinInitialized) {
genuin.initialize({
embed_id: "Your Embed Id",
api_key: "Your Api key",
contextualParams: {
page_context: "e.g AI, LLM, Machine Learning, MLOPS, Robotics",
geo: {
lat: 50.432, // latitude of location in number , e.g. 50.432,
long: 122.4194, // longitude of location in number , e.g. 122.4194,
},
},
});
this.genuinInitialized = true;
}
};
this.scriptElement = document.createElement("script");
this.scriptElement.src = "https://media.begenuin.com/sdk/gen_sdk.min.js";
this.scriptElement.async = true;
document.body.appendChild(this.scriptElement);
}
ngOnDestroy() {
if (this.scriptElement) {
document.body.removeChild(this.scriptElement);
}
delete (window as any).onGenuinReady;
}
}
// src/app/app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
import { GenuinSdkComponent } from "./genuin-sdk.component";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, GenuinSdkComponent],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
```
### React Structure
**Note** : If you prefer not to inject the script dynamically using JavaScript, you can also include it directly in your HTML using a script tag.
However, before initializing or interacting with the embedded element, ensure the
following:
1. The script has finished loading successfully.
2. The target DOM element is present on the page.
#### Single embeds (React)
```jsx Embed_Without_AutoLogin theme={null}
// src/App.tsx
import { useEffect, useRef } from "react";
export default function App() {
const initializedRef = useRef(false);
useEffect(() => {
if (initializedRef.current) return;
initializedRef.current = true;
const scriptSrc = "https://media.begenuin.com/sdk/gen_sdk.min.js";
const script = document.createElement("script");
script.src = scriptSrc;
script.async = true;
script.onload = () => {
if (window.genuin) {
window.genuin.init({});
}
};
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, []);
return (
);
}
```
```jsx Embed_With_AutoLogin theme={null}
// src/App.tsx
import { useEffect, useRef } from "react";
export default function App() {
const initializedRef = useRef(false);
useEffect(() => {
if (initializedRef.current) return;
initializedRef.current = true;
const scriptSrc = "https://media.begenuin.com/sdk/gen_sdk.min.js";
const script = document.createElement("script");
script.src = scriptSrc;
script.async = true;
script.onload = () => {
if (window.genuin) {
window.genuin.init({
token: "Your Authentication Token",
params: {
name: "Name",
mobile: "Contact Number",
email: "Email ID",
nickname: "Nickname",
profileImage: "Profile Image URL",
},
// Pass the token only if you want to enable autologin functionality.
// The token value can be a unique identifier (such as a session token) or an email address, depending on your authentication flow.
// To bypass autologin, provide the token along with any additional required parameters.
// Include only the parameters necessary for your use case.
});
}
};
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, []);
return (
);
}
```
#### Embed With Multi Embeds (React)
##### Prerequisites
Before implementing the multi-embed setup, ensure you have:
1. Valid Genuin API credentials
2. Unique embed IDs for each widget instance
3. Access to the Genuin SDK
The multi-embed approach requires separate containers for each widget instance. Each container
must have unique identifiers and proper data attributes.
**Note:**
1. Ensure each container has a unique `id` attribute
2. The multi-embed approach also works for single embeds, so you can use it for both cases if you prefer a unified setup.
```jsx Embed_With_Multi_Embeds theme={null}
// /src/App.tsx
import { useEffect, useRef } from "react";
export default function App() {
const initializedRef = useRef(false);
useEffect(() => {
if (initializedRef.current) return;
initializedRef.current = true;
const scriptSrc = "https://media.begenuin.com/sdk/gen_sdk.min.js";
const script = document.createElement("script");
script.src = scriptSrc;
script.async = true;
script.onload = () => {
if (window.genuin) {
window.genuin.init({});
}
};
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, []);
return (
<>
>
);
}
function FirstComponent() {
return (
);
}
function SecondComponent() {
return (
);
}
```
#### Embed With Contextual Feed (React)
Only include the parameters necessary to retrieve a contextual feed.
```jsx Contextual_Feed theme={null}
// src/App.tsx
import { useEffect, useRef } from "react";
export default function App() {
const initializedRef = useRef(false);
useEffect(() => {
if (initializedRef.current) return;
initializedRef.current = true;
const scriptSrc = "https://media.begenuin.com/sdk/gen_sdk.min.js";
const script = document.createElement("script");
script.src = scriptSrc;
script.async = true;
script.onload = () => {
if (window.genuin) {
window.genuin.init({});
}
};
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, []);
return (
<>
>
);
}
function FirstComponent() {
return (
);
}
function SecondComponent() {
return (
);
}
```
### NextJs Structure
#### Single Embeds (NextJs)
```typescript Embed_Without_AutoLogin theme={null}
// app/GenuinSDK.tsx
"use client";
import Script from "next/script";
import { useEffect } from "react";
export default function GenuinSDK() {
useEffect(() => {
window.genuin.init({});
}, []);
return (
<>
>
);
}
// app/page.tsx
'use client';
import GenuinSDK from './GenuinSDK';
export default function Home() {
return (
<>
>
);
}
```
```typescript Embed_With_AutoLogin theme={null}
// app/GenuinSDK.tsx
"use client";
import Script from "next/script";
import { useEffect } from "react";
export default function GenuinSDK() {
useEffect(() => {
window.genuin.init({
token: "Your Authentication Token",
params: {
name: "Name",
mobile: "Contact Number",
email: "Email ID",
nickname: "Nickname",
profileImage: "Profile Image URL",
},
// Pass the token only if you want to enable autologin functionality.
// The token value can be a unique identifier (such as a session token) or an email address, depending on your authentication flow.
// To bypass autologin, provide the token along with any additional required parameters.
// Include only the parameters necessary for your use case.
});
}, []);
return (
<>
>
);
}
// app/page.tsx
("use client");
import GenuinSDK from "./GenuinSDK";
export default function Home() {
return (
<>
>
);
}
```
#### Embed With Multi Embeds (NextJs)
##### Prerequisites
Before implementing the multi-embed setup, ensure you have:
1. Valid Genuin API credentials
2. Unique embed IDs for each widget instance
3. Access to the Genuin SDK
The multi-embed approach requires separate containers for each widget instance. Each container
must have unique identifiers and proper data attributes.
**Note:**
1. Ensure each container has a unique `id` attribute
2. The multi-embed approach also works for single embeds, so you can use it for both cases if you prefer a unified setup.
```typescript Embed_With_Multi_Embeds theme={null}
// app/GenuinSDK.tsx
"use client";
import Script from "next/script";
import { useEffect } from "react";
export default function GenuinSDK() {
useEffect(() => {
window.genuin.init({});
}, []);
return (
<>
>
);
}
// app/page.tsx
"use client";
import GenuinSDK from "./GenuinSDK";
export default function Home() {
return (
<>
>
);
}
```
#### Embed With Contextual Feed (NextJs)
Only include the parameters necessary to retrieve a contextual feed.
```typescript Contextual_Feed theme={null}
// app/GenuinSDK.tsx
"use client";
import Script from "next/script";
import { useEffect } from "react";
export default function GenuinSDK() {
useEffect(() => {
window.genuin.init({});
}, []);
return (
<>
>
);
}
// app/page.tsx
"use client";
import GenuinSDK from "./GenuinSDK";
export default function Home() {
return (
<>
>
);
}
```
### Customisation
#### Font Family
To apply your application's custom font styles to the Genuin Web SDK, add the following style block inside the head tag:
**Note:** Please ensure that your custom font is correctly loaded on the page. If the specified font is not available, the SDK will automatically fall back to the default system font.
```html theme={null}
```
#### Direct Video Page Redirection
You can use the video parameter during SDK initialization—alongside other parameters—to directly open a specific video page instead of loading the default feed.
```html Single_Embeds theme={null}
window.genuin.init({
video : "VIDEO_SLUG e.g. excerpt-from-preserving-the-vasa-httpsyoutubethbk"
})
```
```html Multi_Embeds theme={null}
```
### SDK API's
#### Auth Callback
The SDK provides a mechanism to optionally override the default authentication behavior by exposing a `genuinAuth` callback on the global `window` object.
This is particularly useful when you want full control over how your application handles login or other auth-related actions — such as redirecting to a custom login page or integrating with an existing auth provider.
```html theme={null}
window.genuinAuth = (data) => {
// You can trigger your own login mechanism
// Option 1: Use a custom redirect function
redirectToLogin();
// Option 2: Directly set the login URL
// window.location.href = `URL`;
};
```
##### Auth Callback Parameters
The auth callback passes certain parameters that allow you to perform necessary actions after a user is successfully logged in or redirected — depending on the flow you’ve implemented.
For example, it includes returnQueryParams, which is a string containing query parameters that indicate the context in which the auth callback was triggered.
This helps determine what action should be taken.
Example: If a user is trying to comment on a post and the auth callback is triggered, returnQueryParams might include action=comment.
You can extract this action parameter and pass it to the embed to perform the corresponding operation.
**Note** : To use this, you must have the genuin auth callback implemented, the user must be logged in, and you must pass the video slug as well.
```html theme={null}
window.genuinAuth = (data) => {
// Trigger your login mechanism here
// Option 1: Use a custom redirect function
redirectToLogin();
// Option 2: Directly redirect to login URL
// window.location.href = `LOGIN_URL`;
// data.returnQueryParams contains the query parameters
const params = new URLSearchParams(data.returnQueryParams);
const action = params.get("action");
// Pass the above `action` value to the embeds below.
// There are two ways to pass this: via init or via data-attribute
};
window.genuin.init({
action: 'Pass action to perform, e.g., comment',
video: 'VIDEO_SLUG'
});
```
#### Dynamically Update SDK Context
You can use the update() method to dynamically change the SDK’s contextual parameters at any point after initialization. This is especially useful when the page content changes based on user interaction (e.g., clicking a new topic, navigating to a different section) and you want the feed to reflect the new context without reinitializing the SDK.
```html Single_Embeds theme={null}
window.genuin.update({
contextualParams : {
page_context: "e.g AI, LLM, Machine Learning, MLOPS, Robotics",
geo: {
lat: 50.432, // latitude of location in number , e.g. 50.432,
long: 122.4194, // longitude of location in number , e.g. 122.4194,
},
}
})
```
```html Multi_Embeds theme={null}
// Pass the element ID along with the contextual parameters to update the SDK's contextual parameters for that specific element.
window.genuin.update({
id : "gen-sdk-1",
contextualParams : {
page_context: "e.g AI, LLM, Machine Learning, MLOPS, Robotics",
geo: {
lat: 50.432, // latitude of location in number , e.g. 50.432,
long: 122.4194, // longitude of location in number , e.g. 122.4194,
},
}
})
```
## Configuration Parameters
| **Setting** | **Description** |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| embed\_id | The id which you want to embed in your web SDK |
| api\_key | Unique API key which will be used to authenticate the embed |
| token | Your autologin Token which will be used for authenticate |
| page\_context | The content or context of your webpage, used to render relevant embed feeds. This can include comma-separated keywords or search parameters (e.g., "AI", "tech news", etc.). |
| lat | Latitude of Location which will be used to retrieve the feed based on Location |
| long | Longitude of location which will be used to retrieve the feed based on Location |
| name | Full name of the user for automatic login (Autologin) |
| mobile | Mobile number or contact information of the user for authentication |
| email | Email address of the user for authentication and communication |
| nickname | Display nickname or username for the autologged user |
| profileImage | URL of the user's profile image to personalize the embedded experience |
# The All-in-One CRM & Support
Source: https://resources.begenuin.com/faqs/Use_your_community_destination_as_all_in_one_crm_newsletter_&_customer_support
In today’s digital-first world, businesses and brands need smarter ways to engage their customers, build loyalty, and streamline communication. What if your community could become more than just a group of members? What if it could serve as a centralized hub for CRM, newsletters, and customer support? With our product, you can do exactly that - by integrating vertical video powered communities into your app and web ecosystem. For brands, this translates to a centralized platform where customers can have the vertical video experience - they can view the content about products and services, engage with the content, and can share the content.
Instead of relying on separate tools for each function, why not **centralize everything in one place**? In this article, we'll explore how you can transform your **community destination into an all-in-one CRM, Newsletter & customer support** that helps you manage customer interactions, send targeted communications, and provide seamless support - all while building deeper relationships with your audience.
## 1. Your Community Destination for CRM (Customer Relationship Management)
### What is CRM and Why Does It Matter?
CRM refers to tools and strategies that help businesses manage interactions with existing and potential customers. Traditionally, businesses use dedicated CRM platforms like Salesforce, HubSpot, or Zoho, but if your community destination is already engaging with your customers, you can use it as an alternative to traditional CRM tools.
### How Your Community Destination Functions as a CRM
Your community contains **rich user data**, including:
* **User interactions** – Who is actively engaging, what topics interest them, and how they respond to your content.
* **Purchase behavior** – If linked with your product or service through linkouts in video content, you can track which community members are purchasing which products.
* **Feedback & sentiments** – You can gauge customer satisfaction by monitoring comments, user generated content.
* **Segmentation & personalization** – Users in your community can be categorized based on interests, purchase history, or behavior, allowing for **targeted outreach**.
Our **Brand Control Centre (admin portal)** that allows Brands to **manage their contacts** effectively and track outreach campaign analytics. This feature gives brands insights into user engagement, helping them make data-driven decisions to optimize their communication strategies.
The image below showcases how contacts and their respective email campaigns can be tracked, giving brands a clear view of **contact name, status, email, role, sent - opened - clicked analytics**. Brand can also create and import new contacts by clicking “Add contacts”
### Example Use Cases
An eCommerce brand like **Ogonuts** - on their community destination, they analyze user engagement on specific content to identify frequent shoppers and engage them with personalized offers, like discounts on their favorite nuts or exclusive early access to new flavors. They can see all their community members, admins as contacts in the brand control centre as well as at the community destination in their app and web (O\&O properties).
## 2. Your Community as a Newsletter & Content Distribution Channel
TraditionalEmail newsletters are effective but have limitations:
* Open rates typically range from 20-30% (many emails go unread).
* Emails often get lost in cluttered inboxes.
* Engagement is one-way—users receive content but rarely interact.
### How to Use Your Community for the Newsletters
* **Pin videos in your groups within your community** with key updates, new product launches, and upcoming events.
* **Customize your email newsletter** with community updates, Highlights & most engaged posts within your community and send it to all the contacts or your personalised contacts list based on their interests as well using our brand control centre
* **Create an automation workflow** where you schedule email updates for weekly updates, features discussion or exclusive insights, You can personalize it with event triggers and contacts list using our brand control centre.
Our Brand Control Centre allows you to view all the email updates and can customize your email updates. The below image represents the email outreach dashboard within the Brand Control Centre. It provides a structured overview of:
* **Different email templates** used for engagement.
* **Activation status** of each email campaign.
* **Sent, opened, and clicked metrics**, helping admins gauge performance.
* **Options to view details and edit email campaigns**, ensuring continuous optimization.
With such a dashboard, businesses can effectively manage outreach, improve communication strategies, and enhance customer engagement via Emails, SMS and in-app notifications as well with the community-driven approach.
Below image shows that brand admin can customize the email template where community insights can be added, top most engaged post by users can be added in a way that it's a most engaged highlights while it is being sent to your customers.
**By using your community as a newsletter platform, you**:
* **Ensure higher visibility** - your content is seen in active discussions rather than an inbox.
* **Encourage interaction** - members can immediately comment, ask questions, and share insights.
* **Create a more organic experience** - content feels like part of the community rather than a formal broadcast.
Community-driven email newsletters consistently achieve open rates of around 40%, significantly outperforming traditional email newsletters, which typically see open rates between 20-30%.
### Example Use Case
Ogonuts, an ecommerce brand specializing in selling guilt-free, wholesome, nutrition snacks, utilizes the community platform to foster an engaging content. With the community members, Ogonuts publishes a weekly content having "Community Digest" showcasing popular recipes, member success stories, and upcoming product launches. It also sends community highlights from the brand control centre as a newsletter. This strategy cultivates higher engagement and conversions by 15% compared to traditional email newsletters, as members actively interact with the content and each other.
## 3. Your Community as a Customer Support Hub
Your community can evolve into a dynamic customer support center where customers find solutions and receive assistance. Having a dedicated group within your community which can have the content of knowledge base equipped with FAQs content and troubleshooting content empowers customers to self-serve. Peer-to-peer support within the community leads to a collaborative environment where customers share knowledge and experiences.
### How to Implement Community-Driven Support
* **Create dedicated support channels** - separate groups for troubleshooting, FAQs, and feature requests etc.
* **Encourage peer-to-peer support** - power users and brand creators can assist new users and solve queries from other new users.
* **Monitor & escalate critical issues** - ensure that unresolved concerns are addressed by official support teams.
### Example Use Case
Ogonuts, an ecommerce brand specializing in selling guilt-free, wholesome, nutrition snacks, could establish a group within their communities. Here, customers could discuss their favourite products, share recipes incorporating Ogonuts snacks, and troubleshoot any issues they encounter. This platform would foster a sense of community among customers, while simultaneously reducing the burden on Ogonuts' customer support team. For instance, a customer might inquire by posting a video about using Ogonuts' workout boosts super snack in a specific recipe, and another customer with prior experience could offer suggestions or advice by commenting on the same video or post images in comments.
# Brand Community SEO and LLM Discoverability
Source: https://resources.begenuin.com/faqs/brand_community_seo_and_llm_discoverability
How community content is optimized for SEO and discoverability by search engines and LLMs
**Introduction**
This article addresses the question of how content in a brand community is discoverable by search engines and Large Language Models (LLMs), and how this process contributes to SEO. It provides information to ensure that brand communities are optimized for both traditional web crawlers and AI-driven discovery.
# Section 1: Brand Communities and Content Discoverability by Search Engines
We follow standard practices for SEO, including optimizing URLs, titles, and descriptions, as well as incorporating relevant keywords.
## 1.1 SEO Attributes for Enhanced Discoverability
The attached sheet details the attributes at the community, group, post, and profile levels that contribute to SEO and greater discoverability by search engines - [SEO : Genuin Page Meta Attributes - Sephora](https://docs.google.com/spreadsheets/d/13xcU0Vvqq7oAN-ETV7_Z04b6XKB7VcDoGyqeRCMa8VM/edit?usp=sharing)
**Table 1**. Pagewise meta attributes mapping
| Meta Attribute | Subdomain Page | Community Detail Page | Group Detail Page | Post/Video Page | Brand Profile Page | User Profile Page |
| ------------------------ | -------------------------------------- | --------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------- |
| **description** | Brand's Bio | Community Description | \ \| Join \ to talk about it | Watch videos from \ on \ | Meta Description for sharing Brand URL | \ (@username) on \ |
| **og:title** | Brand's Full Name | Community Name | Group Name | \